@vue/compiler-dom 3.1.1 → 3.1.5

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.
@@ -48,11 +48,20 @@ var VueCompilerDOM = (function (exports) {
48
48
 
49
49
  const range = 2;
50
50
  function generateCodeFrame(source, start = 0, end = source.length) {
51
- const lines = source.split(/\r?\n/);
51
+ // Split the content into individual lines but capture the newline sequence
52
+ // that separated each line. This is important because the actual sequence is
53
+ // needed to properly take into account the full line length for offset
54
+ // comparison
55
+ let lines = source.split(/(\r?\n)/);
56
+ // Separate the lines and newline sequences into separate arrays for easier referencing
57
+ const newlineSequences = lines.filter((_, idx) => idx % 2 === 1);
58
+ lines = lines.filter((_, idx) => idx % 2 === 0);
52
59
  let count = 0;
53
60
  const res = [];
54
61
  for (let i = 0; i < lines.length; i++) {
55
- count += lines[i].length + 1;
62
+ count +=
63
+ lines[i].length +
64
+ ((newlineSequences[i] && newlineSequences[i].length) || 0);
56
65
  if (count >= start) {
57
66
  for (let j = i - range; j <= i + range || end > count; j++) {
58
67
  if (j < 0 || j >= lines.length)
@@ -60,9 +69,10 @@ var VueCompilerDOM = (function (exports) {
60
69
  const line = j + 1;
61
70
  res.push(`${line}${' '.repeat(Math.max(3 - String(line).length, 0))}| ${lines[j]}`);
62
71
  const lineLength = lines[j].length;
72
+ const newLineSeqLength = (newlineSequences[j] && newlineSequences[j].length) || 0;
63
73
  if (j === i) {
64
74
  // push underline
65
- const pad = start - (count - lineLength) + 1;
75
+ const pad = start - (count - (lineLength + newLineSeqLength));
66
76
  const length = Math.max(1, end > count ? lineLength - pad : end - start);
67
77
  res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
68
78
  }
@@ -71,7 +81,7 @@ var VueCompilerDOM = (function (exports) {
71
81
  const length = Math.max(Math.min(end - count, lineLength), 1);
72
82
  res.push(` | ` + '^'.repeat(length));
73
83
  }
74
- count += lineLength + 1;
84
+ count += lineLength + newLineSeqLength;
75
85
  }
76
86
  }
77
87
  break;
@@ -518,18 +528,84 @@ var VueCompilerDOM = (function (exports) {
518
528
  }
519
529
  const nonIdentifierRE = /^\d|[^\$\w]/;
520
530
  const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
521
- const memberExpRE = /^[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*(?:\s*\.\s*[A-Za-z_$\xA0-\uFFFF][\w$\xA0-\uFFFF]*|\[(.+)\])*$/;
531
+ const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/;
532
+ const validIdentCharRE = /[\.\?\w$\xA0-\uFFFF]/;
533
+ const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g;
534
+ /**
535
+ * Simple lexer to check if an expression is a member expression. This is
536
+ * lax and only checks validity at the root level (i.e. does not validate exps
537
+ * inside square brackets), but it's ok since these are only used on template
538
+ * expressions and false positives are invalid expressions in the first place.
539
+ */
522
540
  const isMemberExpression = (path) => {
523
- if (!path)
524
- return false;
525
- const matched = memberExpRE.exec(path.trim());
526
- if (!matched)
527
- return false;
528
- if (!matched[1])
529
- return true;
530
- if (!/[\[\]]/.test(matched[1]))
531
- return true;
532
- return isMemberExpression(matched[1].trim());
541
+ // remove whitespaces around . or [ first
542
+ path = path.trim().replace(whitespaceRE, s => s.trim());
543
+ let state = 0 /* inMemberExp */;
544
+ let stateStack = [];
545
+ let currentOpenBracketCount = 0;
546
+ let currentOpenParensCount = 0;
547
+ let currentStringType = null;
548
+ for (let i = 0; i < path.length; i++) {
549
+ const char = path.charAt(i);
550
+ switch (state) {
551
+ case 0 /* inMemberExp */:
552
+ if (char === '[') {
553
+ stateStack.push(state);
554
+ state = 1 /* inBrackets */;
555
+ currentOpenBracketCount++;
556
+ }
557
+ else if (char === '(') {
558
+ stateStack.push(state);
559
+ state = 2 /* inParens */;
560
+ currentOpenParensCount++;
561
+ }
562
+ else if (!(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)) {
563
+ return false;
564
+ }
565
+ break;
566
+ case 1 /* inBrackets */:
567
+ if (char === `'` || char === `"` || char === '`') {
568
+ stateStack.push(state);
569
+ state = 3 /* inString */;
570
+ currentStringType = char;
571
+ }
572
+ else if (char === `[`) {
573
+ currentOpenBracketCount++;
574
+ }
575
+ else if (char === `]`) {
576
+ if (!--currentOpenBracketCount) {
577
+ state = stateStack.pop();
578
+ }
579
+ }
580
+ break;
581
+ case 2 /* inParens */:
582
+ if (char === `'` || char === `"` || char === '`') {
583
+ stateStack.push(state);
584
+ state = 3 /* inString */;
585
+ currentStringType = char;
586
+ }
587
+ else if (char === `(`) {
588
+ currentOpenParensCount++;
589
+ }
590
+ else if (char === `)`) {
591
+ // if the exp ends as a call then it should not be considered valid
592
+ if (i === path.length - 1) {
593
+ return false;
594
+ }
595
+ if (!--currentOpenParensCount) {
596
+ state = stateStack.pop();
597
+ }
598
+ }
599
+ break;
600
+ case 3 /* inString */:
601
+ if (char === currentStringType) {
602
+ state = stateStack.pop();
603
+ currentStringType = null;
604
+ }
605
+ break;
606
+ }
607
+ }
608
+ return !currentOpenBracketCount && !currentOpenParensCount;
533
609
  };
534
610
  function getInnerRange(loc, offset, length) {
535
611
  const source = loc.source.substr(offset, length);
@@ -1098,6 +1174,10 @@ var VueCompilerDOM = (function (exports) {
1098
1174
  const isPreBoundary = context.inPre && !wasInPre;
1099
1175
  const isVPreBoundary = context.inVPre && !wasInVPre;
1100
1176
  if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {
1177
+ // #4030 self-closing <pre> tag
1178
+ if (context.options.isPreTag(element.tag)) {
1179
+ context.inPre = false;
1180
+ }
1101
1181
  return element;
1102
1182
  }
1103
1183
  // Children.
@@ -1153,12 +1233,13 @@ var VueCompilerDOM = (function (exports) {
1153
1233
  // save current state in case we need to re-parse attributes with v-pre
1154
1234
  const cursor = getCursor(context);
1155
1235
  const currentSource = context.source;
1156
- // Attributes.
1157
- let props = parseAttributes(context, type);
1158
1236
  // check <pre> tag
1159
- if (context.options.isPreTag(tag)) {
1237
+ const isPreTag = context.options.isPreTag(tag);
1238
+ if (isPreTag) {
1160
1239
  context.inPre = true;
1161
1240
  }
1241
+ // Attributes.
1242
+ let props = parseAttributes(context, type);
1162
1243
  // check v-pre
1163
1244
  if (type === 0 /* Start */ &&
1164
1245
  !context.inVPre &&
@@ -1205,41 +1286,17 @@ var VueCompilerDOM = (function (exports) {
1205
1286
  }
1206
1287
  }
1207
1288
  let tagType = 0 /* ELEMENT */;
1208
- const options = context.options;
1209
- if (!context.inVPre && !options.isCustomElement(tag)) {
1210
- const hasVIs = props.some(p => {
1211
- if (p.name !== 'is')
1212
- return;
1213
- // v-is="xxx" (TODO: deprecate)
1214
- if (p.type === 7 /* DIRECTIVE */) {
1215
- return true;
1216
- }
1217
- // is="vue:xxx"
1218
- if (p.value && p.value.content.startsWith('vue:')) {
1219
- return true;
1220
- }
1221
- // in compat mode, any is usage is considered a component
1222
- if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
1223
- return true;
1224
- }
1225
- });
1226
- if (options.isNativeTag && !hasVIs) {
1227
- if (!options.isNativeTag(tag))
1228
- tagType = 1 /* COMPONENT */;
1229
- }
1230
- else if (hasVIs ||
1231
- isCoreComponent(tag) ||
1232
- (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
1233
- /^[A-Z]/.test(tag) ||
1234
- tag === 'component') {
1235
- tagType = 1 /* COMPONENT */;
1236
- }
1289
+ if (!context.inVPre) {
1237
1290
  if (tag === 'slot') {
1238
1291
  tagType = 2 /* SLOT */;
1239
1292
  }
1240
- else if (tag === 'template' &&
1241
- props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
1242
- tagType = 3 /* TEMPLATE */;
1293
+ else if (tag === 'template') {
1294
+ if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
1295
+ tagType = 3 /* TEMPLATE */;
1296
+ }
1297
+ }
1298
+ else if (isComponent(tag, props, context)) {
1299
+ tagType = 1 /* COMPONENT */;
1243
1300
  }
1244
1301
  }
1245
1302
  return {
@@ -1254,6 +1311,49 @@ var VueCompilerDOM = (function (exports) {
1254
1311
  codegenNode: undefined // to be created during transform phase
1255
1312
  };
1256
1313
  }
1314
+ function isComponent(tag, props, context) {
1315
+ const options = context.options;
1316
+ if (options.isCustomElement(tag)) {
1317
+ return false;
1318
+ }
1319
+ if (tag === 'component' ||
1320
+ /^[A-Z]/.test(tag) ||
1321
+ isCoreComponent(tag) ||
1322
+ (options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
1323
+ (options.isNativeTag && !options.isNativeTag(tag))) {
1324
+ return true;
1325
+ }
1326
+ // at this point the tag should be a native tag, but check for potential "is"
1327
+ // casting
1328
+ for (let i = 0; i < props.length; i++) {
1329
+ const p = props[i];
1330
+ if (p.type === 6 /* ATTRIBUTE */) {
1331
+ if (p.name === 'is' && p.value) {
1332
+ if (p.value.content.startsWith('vue:')) {
1333
+ return true;
1334
+ }
1335
+ else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
1336
+ return true;
1337
+ }
1338
+ }
1339
+ }
1340
+ else {
1341
+ // directive
1342
+ // v-is (TODO Deprecate)
1343
+ if (p.name === 'is') {
1344
+ return true;
1345
+ }
1346
+ else if (
1347
+ // :is on plain element - only treat as component in compat mode
1348
+ p.name === 'bind' &&
1349
+ isBindKey(p.arg, 'is') &&
1350
+ true &&
1351
+ checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
1352
+ return true;
1353
+ }
1354
+ }
1355
+ }
1356
+ }
1257
1357
  function parseAttributes(context, type) {
1258
1358
  const props = [];
1259
1359
  const attributeNames = new Set();
@@ -2116,7 +2216,7 @@ var VueCompilerDOM = (function (exports) {
2116
2216
  }
2117
2217
 
2118
2218
  const PURE_ANNOTATION = `/*#__PURE__*/`;
2119
- function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssr = false }) {
2219
+ function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssr = false, isTS = false }) {
2120
2220
  const context = {
2121
2221
  mode,
2122
2222
  prefixIdentifiers,
@@ -2127,6 +2227,7 @@ var VueCompilerDOM = (function (exports) {
2127
2227
  runtimeGlobalName,
2128
2228
  runtimeModuleName,
2129
2229
  ssr,
2230
+ isTS,
2130
2231
  source: ast.loc.source,
2131
2232
  code: ``,
2132
2233
  column: 1,
@@ -2282,7 +2383,7 @@ var VueCompilerDOM = (function (exports) {
2282
2383
  newline();
2283
2384
  push(`return `);
2284
2385
  }
2285
- function genAssets(assets, type, { helper, push, newline }) {
2386
+ function genAssets(assets, type, { helper, push, newline, isTS }) {
2286
2387
  const resolver = helper(type === 'filter'
2287
2388
  ? RESOLVE_FILTER
2288
2389
  : type === 'component'
@@ -2295,7 +2396,7 @@ var VueCompilerDOM = (function (exports) {
2295
2396
  if (maybeSelfReference) {
2296
2397
  id = id.slice(0, -6);
2297
2398
  }
2298
- push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`);
2399
+ push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);
2299
2400
  if (i < assets.length - 1) {
2300
2401
  newline();
2301
2402
  }
@@ -3403,7 +3504,8 @@ var VueCompilerDOM = (function (exports) {
3403
3504
  switch (child.type) {
3404
3505
  case 1 /* ELEMENT */:
3405
3506
  if (child.tagType === 2 /* SLOT */ ||
3406
- (child.tagType === 0 /* ELEMENT */ &&
3507
+ ((child.tagType === 0 /* ELEMENT */ ||
3508
+ child.tagType === 3 /* TEMPLATE */) &&
3407
3509
  hasForwardedSlots(child.children))) {
3408
3510
  return true;
3409
3511
  }
@@ -3567,16 +3669,10 @@ var VueCompilerDOM = (function (exports) {
3567
3669
  let { tag } = node;
3568
3670
  // 1. dynamic component
3569
3671
  const isExplicitDynamic = isComponentTag(tag);
3570
- const isProp = findProp(node, 'is') || (!isExplicitDynamic && findDir(node, 'is'));
3672
+ const isProp = findProp(node, 'is');
3571
3673
  if (isProp) {
3572
- if (!isExplicitDynamic && isProp.type === 6 /* ATTRIBUTE */) {
3573
- // <button is="vue:xxx">
3574
- // if not <component>, only is value that starts with "vue:" will be
3575
- // treated as component by the parse phase and reach here, unless it's
3576
- // compat mode where all is values are considered components
3577
- tag = isProp.value.content.replace(/^vue:/, '');
3578
- }
3579
- else {
3674
+ if (isExplicitDynamic ||
3675
+ (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {
3580
3676
  const exp = isProp.type === 6 /* ATTRIBUTE */
3581
3677
  ? isProp.value && createSimpleExpression(isProp.value.content, true)
3582
3678
  : isProp.exp;
@@ -3586,6 +3682,21 @@ var VueCompilerDOM = (function (exports) {
3586
3682
  ]);
3587
3683
  }
3588
3684
  }
3685
+ else if (isProp.type === 6 /* ATTRIBUTE */ &&
3686
+ isProp.value.content.startsWith('vue:')) {
3687
+ // <button is="vue:xxx">
3688
+ // if not <component>, only is value that starts with "vue:" will be
3689
+ // treated as component by the parse phase and reach here, unless it's
3690
+ // compat mode where all is values are considered components
3691
+ tag = isProp.value.content.slice(4);
3692
+ }
3693
+ }
3694
+ // 1.5 v-is (TODO: Deprecate)
3695
+ const isDir = !isExplicitDynamic && findDir(node, 'is');
3696
+ if (isDir && isDir.exp) {
3697
+ return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
3698
+ isDir.exp
3699
+ ]);
3589
3700
  }
3590
3701
  // 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
3591
3702
  const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);
@@ -3669,7 +3780,9 @@ var VueCompilerDOM = (function (exports) {
3669
3780
  }
3670
3781
  // skip is on <component>, or is="vue:xxx"
3671
3782
  if (name === 'is' &&
3672
- (isComponentTag(tag) || (value && value.content.startsWith('vue:')))) {
3783
+ (isComponentTag(tag) ||
3784
+ (value && value.content.startsWith('vue:')) ||
3785
+ (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {
3673
3786
  continue;
3674
3787
  }
3675
3788
  properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
@@ -3692,7 +3805,10 @@ var VueCompilerDOM = (function (exports) {
3692
3805
  }
3693
3806
  // skip v-is and :is on <component>
3694
3807
  if (name === 'is' ||
3695
- (isVBind && isComponentTag(tag) && isBindKey(arg, 'is'))) {
3808
+ (isVBind &&
3809
+ isBindKey(arg, 'is') &&
3810
+ (isComponentTag(tag) ||
3811
+ (isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {
3696
3812
  continue;
3697
3813
  }
3698
3814
  // skip v-on in SSR compilation
@@ -4217,7 +4333,7 @@ var VueCompilerDOM = (function (exports) {
4217
4333
  // _unref(exp)
4218
4334
  context.bindingMetadata[rawExp];
4219
4335
  const maybeRef = !true /* SETUP_CONST */;
4220
- if (!isMemberExpression(expString) && !maybeRef) {
4336
+ if (!expString.trim() || (!isMemberExpression(expString) && !maybeRef)) {
4221
4337
  context.onError(createCompilerError(41 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));
4222
4338
  return createTransformProps();
4223
4339
  }