@vue/compiler-core 3.1.0 → 3.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/compiler-core.cjs.js +142 -62
- package/dist/compiler-core.cjs.prod.js +142 -62
- package/dist/compiler-core.d.ts +7 -1
- package/dist/compiler-core.esm-bundler.js +141 -61
- package/package.json +2 -2
|
@@ -356,18 +356,59 @@ function isCoreComponent(tag) {
|
|
|
356
356
|
}
|
|
357
357
|
const nonIdentifierRE = /^\d|[^\$\w]/;
|
|
358
358
|
const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
|
|
359
|
-
const
|
|
359
|
+
const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/;
|
|
360
|
+
const validIdentCharRE = /[\.\w$\xA0-\uFFFF]/;
|
|
361
|
+
const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g;
|
|
362
|
+
/**
|
|
363
|
+
* Simple lexer to check if an expression is a member expression. This is
|
|
364
|
+
* lax and only checks validity at the root level (i.e. does not validate exps
|
|
365
|
+
* inside square brackets), but it's ok since these are only used on template
|
|
366
|
+
* expressions and false positives are invalid expressions in the first place.
|
|
367
|
+
*/
|
|
360
368
|
const isMemberExpression = (path) => {
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
369
|
+
// remove whitespaces around . or [ first
|
|
370
|
+
path = path.trim().replace(whitespaceRE, s => s.trim());
|
|
371
|
+
let state = 0 /* inMemberExp */;
|
|
372
|
+
let prevState = 0 /* inMemberExp */;
|
|
373
|
+
let currentOpenBracketCount = 0;
|
|
374
|
+
let currentStringType = null;
|
|
375
|
+
for (let i = 0; i < path.length; i++) {
|
|
376
|
+
const char = path.charAt(i);
|
|
377
|
+
switch (state) {
|
|
378
|
+
case 0 /* inMemberExp */:
|
|
379
|
+
if (char === '[') {
|
|
380
|
+
prevState = state;
|
|
381
|
+
state = 1 /* inBrackets */;
|
|
382
|
+
currentOpenBracketCount++;
|
|
383
|
+
}
|
|
384
|
+
else if (!(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)) {
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
break;
|
|
388
|
+
case 1 /* inBrackets */:
|
|
389
|
+
if (char === `'` || char === `"` || char === '`') {
|
|
390
|
+
prevState = state;
|
|
391
|
+
state = 2 /* inString */;
|
|
392
|
+
currentStringType = char;
|
|
393
|
+
}
|
|
394
|
+
else if (char === `[`) {
|
|
395
|
+
currentOpenBracketCount++;
|
|
396
|
+
}
|
|
397
|
+
else if (char === `]`) {
|
|
398
|
+
if (!--currentOpenBracketCount) {
|
|
399
|
+
state = prevState;
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
break;
|
|
403
|
+
case 2 /* inString */:
|
|
404
|
+
if (char === currentStringType) {
|
|
405
|
+
state = prevState;
|
|
406
|
+
currentStringType = null;
|
|
407
|
+
}
|
|
408
|
+
break;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return !currentOpenBracketCount;
|
|
371
412
|
};
|
|
372
413
|
function getInnerRange(loc, offset, length) {
|
|
373
414
|
const source = loc.source.substr(offset, length);
|
|
@@ -936,6 +977,10 @@ function parseElement(context, ancestors) {
|
|
|
936
977
|
const isPreBoundary = context.inPre && !wasInPre;
|
|
937
978
|
const isVPreBoundary = context.inVPre && !wasInVPre;
|
|
938
979
|
if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {
|
|
980
|
+
// #4030 self-closing <pre> tag
|
|
981
|
+
if (context.options.isPreTag(element.tag)) {
|
|
982
|
+
context.inPre = false;
|
|
983
|
+
}
|
|
939
984
|
return element;
|
|
940
985
|
}
|
|
941
986
|
// Children.
|
|
@@ -991,12 +1036,13 @@ function parseTag(context, type, parent) {
|
|
|
991
1036
|
// save current state in case we need to re-parse attributes with v-pre
|
|
992
1037
|
const cursor = getCursor(context);
|
|
993
1038
|
const currentSource = context.source;
|
|
994
|
-
// Attributes.
|
|
995
|
-
let props = parseAttributes(context, type);
|
|
996
1039
|
// check <pre> tag
|
|
997
|
-
|
|
1040
|
+
const isPreTag = context.options.isPreTag(tag);
|
|
1041
|
+
if (isPreTag) {
|
|
998
1042
|
context.inPre = true;
|
|
999
1043
|
}
|
|
1044
|
+
// Attributes.
|
|
1045
|
+
let props = parseAttributes(context, type);
|
|
1000
1046
|
// check v-pre
|
|
1001
1047
|
if (type === 0 /* Start */ &&
|
|
1002
1048
|
!context.inVPre &&
|
|
@@ -1043,41 +1089,17 @@ function parseTag(context, type, parent) {
|
|
|
1043
1089
|
}
|
|
1044
1090
|
}
|
|
1045
1091
|
let tagType = 0 /* ELEMENT */;
|
|
1046
|
-
|
|
1047
|
-
if (!context.inVPre && !options.isCustomElement(tag)) {
|
|
1048
|
-
const hasVIs = props.some(p => {
|
|
1049
|
-
if (p.name !== 'is')
|
|
1050
|
-
return;
|
|
1051
|
-
// v-is="xxx" (TODO: deprecate)
|
|
1052
|
-
if (p.type === 7 /* DIRECTIVE */) {
|
|
1053
|
-
return true;
|
|
1054
|
-
}
|
|
1055
|
-
// is="vue:xxx"
|
|
1056
|
-
if (p.value && p.value.content.startsWith('vue:')) {
|
|
1057
|
-
return true;
|
|
1058
|
-
}
|
|
1059
|
-
// in compat mode, any is usage is considered a component
|
|
1060
|
-
if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1061
|
-
return true;
|
|
1062
|
-
}
|
|
1063
|
-
});
|
|
1064
|
-
if (options.isNativeTag && !hasVIs) {
|
|
1065
|
-
if (!options.isNativeTag(tag))
|
|
1066
|
-
tagType = 1 /* COMPONENT */;
|
|
1067
|
-
}
|
|
1068
|
-
else if (hasVIs ||
|
|
1069
|
-
isCoreComponent(tag) ||
|
|
1070
|
-
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
|
1071
|
-
/^[A-Z]/.test(tag) ||
|
|
1072
|
-
tag === 'component') {
|
|
1073
|
-
tagType = 1 /* COMPONENT */;
|
|
1074
|
-
}
|
|
1092
|
+
if (!context.inVPre) {
|
|
1075
1093
|
if (tag === 'slot') {
|
|
1076
1094
|
tagType = 2 /* SLOT */;
|
|
1077
1095
|
}
|
|
1078
|
-
else if (tag === 'template'
|
|
1079
|
-
props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
|
|
1080
|
-
|
|
1096
|
+
else if (tag === 'template') {
|
|
1097
|
+
if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
|
|
1098
|
+
tagType = 3 /* TEMPLATE */;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1101
|
+
else if (isComponent(tag, props, context)) {
|
|
1102
|
+
tagType = 1 /* COMPONENT */;
|
|
1081
1103
|
}
|
|
1082
1104
|
}
|
|
1083
1105
|
return {
|
|
@@ -1092,6 +1114,49 @@ function parseTag(context, type, parent) {
|
|
|
1092
1114
|
codegenNode: undefined // to be created during transform phase
|
|
1093
1115
|
};
|
|
1094
1116
|
}
|
|
1117
|
+
function isComponent(tag, props, context) {
|
|
1118
|
+
const options = context.options;
|
|
1119
|
+
if (options.isCustomElement(tag)) {
|
|
1120
|
+
return false;
|
|
1121
|
+
}
|
|
1122
|
+
if (tag === 'component' ||
|
|
1123
|
+
/^[A-Z]/.test(tag) ||
|
|
1124
|
+
isCoreComponent(tag) ||
|
|
1125
|
+
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
|
1126
|
+
(options.isNativeTag && !options.isNativeTag(tag))) {
|
|
1127
|
+
return true;
|
|
1128
|
+
}
|
|
1129
|
+
// at this point the tag should be a native tag, but check for potential "is"
|
|
1130
|
+
// casting
|
|
1131
|
+
for (let i = 0; i < props.length; i++) {
|
|
1132
|
+
const p = props[i];
|
|
1133
|
+
if (p.type === 6 /* ATTRIBUTE */) {
|
|
1134
|
+
if (p.name === 'is' && p.value) {
|
|
1135
|
+
if (p.value.content.startsWith('vue:')) {
|
|
1136
|
+
return true;
|
|
1137
|
+
}
|
|
1138
|
+
else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1139
|
+
return true;
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
else {
|
|
1144
|
+
// directive
|
|
1145
|
+
// v-is (TODO Deprecate)
|
|
1146
|
+
if (p.name === 'is') {
|
|
1147
|
+
return true;
|
|
1148
|
+
}
|
|
1149
|
+
else if (
|
|
1150
|
+
// :is on plain element - only treat as component in compat mode
|
|
1151
|
+
p.name === 'bind' &&
|
|
1152
|
+
isBindKey(p.arg, 'is') &&
|
|
1153
|
+
true &&
|
|
1154
|
+
checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1155
|
+
return true;
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
}
|
|
1095
1160
|
function parseAttributes(context, type) {
|
|
1096
1161
|
const props = [];
|
|
1097
1162
|
const attributeNames = new Set();
|
|
@@ -1988,7 +2053,7 @@ function createStructuralDirectiveTransform(name, fn) {
|
|
|
1988
2053
|
|
|
1989
2054
|
const PURE_ANNOTATION = `/*#__PURE__*/`;
|
|
1990
2055
|
const WITH_ID = `_withId`;
|
|
1991
|
-
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 }) {
|
|
2056
|
+
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, isTS = false }) {
|
|
1992
2057
|
const context = {
|
|
1993
2058
|
mode,
|
|
1994
2059
|
prefixIdentifiers,
|
|
@@ -1999,6 +2064,7 @@ function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode
|
|
|
1999
2064
|
runtimeGlobalName,
|
|
2000
2065
|
runtimeModuleName,
|
|
2001
2066
|
ssr,
|
|
2067
|
+
isTS,
|
|
2002
2068
|
source: ast.loc.source,
|
|
2003
2069
|
code: ``,
|
|
2004
2070
|
column: 1,
|
|
@@ -2278,7 +2344,7 @@ function genModulePreamble(ast, context, genScopeId, inline) {
|
|
|
2278
2344
|
push(`export `);
|
|
2279
2345
|
}
|
|
2280
2346
|
}
|
|
2281
|
-
function genAssets(assets, type, { helper, push, newline }) {
|
|
2347
|
+
function genAssets(assets, type, { helper, push, newline, isTS }) {
|
|
2282
2348
|
const resolver = helper(type === 'filter'
|
|
2283
2349
|
? RESOLVE_FILTER
|
|
2284
2350
|
: type === 'component'
|
|
@@ -2291,7 +2357,7 @@ function genAssets(assets, type, { helper, push, newline }) {
|
|
|
2291
2357
|
if (maybeSelfReference) {
|
|
2292
2358
|
id = id.slice(0, -6);
|
|
2293
2359
|
}
|
|
2294
|
-
push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`);
|
|
2360
|
+
push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);
|
|
2295
2361
|
if (i < assets.length - 1) {
|
|
2296
2362
|
newline();
|
|
2297
2363
|
}
|
|
@@ -3968,16 +4034,10 @@ function resolveComponentType(node, context, ssr = false) {
|
|
|
3968
4034
|
let { tag } = node;
|
|
3969
4035
|
// 1. dynamic component
|
|
3970
4036
|
const isExplicitDynamic = isComponentTag(tag);
|
|
3971
|
-
const isProp = findProp(node, 'is')
|
|
4037
|
+
const isProp = findProp(node, 'is');
|
|
3972
4038
|
if (isProp) {
|
|
3973
|
-
if (
|
|
3974
|
-
|
|
3975
|
-
// if not <component>, only is value that starts with "vue:" will be
|
|
3976
|
-
// treated as component by the parse phase and reach here, unless it's
|
|
3977
|
-
// compat mode where all is values are considered components
|
|
3978
|
-
tag = isProp.value.content.replace(/^vue:/, '');
|
|
3979
|
-
}
|
|
3980
|
-
else {
|
|
4039
|
+
if (isExplicitDynamic ||
|
|
4040
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {
|
|
3981
4041
|
const exp = isProp.type === 6 /* ATTRIBUTE */
|
|
3982
4042
|
? isProp.value && createSimpleExpression(isProp.value.content, true)
|
|
3983
4043
|
: isProp.exp;
|
|
@@ -3987,6 +4047,21 @@ function resolveComponentType(node, context, ssr = false) {
|
|
|
3987
4047
|
]);
|
|
3988
4048
|
}
|
|
3989
4049
|
}
|
|
4050
|
+
else if (isProp.type === 6 /* ATTRIBUTE */ &&
|
|
4051
|
+
isProp.value.content.startsWith('vue:')) {
|
|
4052
|
+
// <button is="vue:xxx">
|
|
4053
|
+
// if not <component>, only is value that starts with "vue:" will be
|
|
4054
|
+
// treated as component by the parse phase and reach here, unless it's
|
|
4055
|
+
// compat mode where all is values are considered components
|
|
4056
|
+
tag = isProp.value.content.slice(4);
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
// 1.5 v-is (TODO: Deprecate)
|
|
4060
|
+
const isDir = !isExplicitDynamic && findDir(node, 'is');
|
|
4061
|
+
if (isDir && isDir.exp) {
|
|
4062
|
+
return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
|
|
4063
|
+
isDir.exp
|
|
4064
|
+
]);
|
|
3990
4065
|
}
|
|
3991
4066
|
// 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
|
|
3992
4067
|
const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);
|
|
@@ -4130,7 +4205,9 @@ function buildProps(node, context, props = node.props, ssr = false) {
|
|
|
4130
4205
|
}
|
|
4131
4206
|
// skip is on <component>, or is="vue:xxx"
|
|
4132
4207
|
if (name === 'is' &&
|
|
4133
|
-
(isComponentTag(tag) ||
|
|
4208
|
+
(isComponentTag(tag) ||
|
|
4209
|
+
(value && value.content.startsWith('vue:')) ||
|
|
4210
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {
|
|
4134
4211
|
continue;
|
|
4135
4212
|
}
|
|
4136
4213
|
properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
|
|
@@ -4153,7 +4230,10 @@ function buildProps(node, context, props = node.props, ssr = false) {
|
|
|
4153
4230
|
}
|
|
4154
4231
|
// skip v-is and :is on <component>
|
|
4155
4232
|
if (name === 'is' ||
|
|
4156
|
-
(isVBind &&
|
|
4233
|
+
(isVBind &&
|
|
4234
|
+
isBindKey(arg, 'is') &&
|
|
4235
|
+
(isComponentTag(tag) ||
|
|
4236
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {
|
|
4157
4237
|
continue;
|
|
4158
4238
|
}
|
|
4159
4239
|
// skip v-on in SSR compilation
|
|
@@ -4337,7 +4417,7 @@ function buildDirectiveArgs(dir, context) {
|
|
|
4337
4417
|
else {
|
|
4338
4418
|
// user directive.
|
|
4339
4419
|
// see if we have directives exposed via <script setup>
|
|
4340
|
-
const fromSetup = resolveSetupReference(dir.name, context);
|
|
4420
|
+
const fromSetup = resolveSetupReference('v-' + dir.name, context);
|
|
4341
4421
|
if (fromSetup) {
|
|
4342
4422
|
dirArgs.push(fromSetup);
|
|
4343
4423
|
}
|
|
@@ -4737,7 +4817,7 @@ const transformModel = (dir, node, context) => {
|
|
|
4737
4817
|
const maybeRef = context.inline &&
|
|
4738
4818
|
bindingType &&
|
|
4739
4819
|
bindingType !== "setup-const" /* SETUP_CONST */;
|
|
4740
|
-
if (!isMemberExpression(expString) && !maybeRef) {
|
|
4820
|
+
if (!expString.trim() || (!isMemberExpression(expString) && !maybeRef)) {
|
|
4741
4821
|
context.onError(createCompilerError(41 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));
|
|
4742
4822
|
return createTransformProps();
|
|
4743
4823
|
}
|
|
@@ -355,18 +355,59 @@ function isCoreComponent(tag) {
|
|
|
355
355
|
}
|
|
356
356
|
const nonIdentifierRE = /^\d|[^\$\w]/;
|
|
357
357
|
const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
|
|
358
|
-
const
|
|
358
|
+
const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/;
|
|
359
|
+
const validIdentCharRE = /[\.\w$\xA0-\uFFFF]/;
|
|
360
|
+
const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g;
|
|
361
|
+
/**
|
|
362
|
+
* Simple lexer to check if an expression is a member expression. This is
|
|
363
|
+
* lax and only checks validity at the root level (i.e. does not validate exps
|
|
364
|
+
* inside square brackets), but it's ok since these are only used on template
|
|
365
|
+
* expressions and false positives are invalid expressions in the first place.
|
|
366
|
+
*/
|
|
359
367
|
const isMemberExpression = (path) => {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
368
|
+
// remove whitespaces around . or [ first
|
|
369
|
+
path = path.trim().replace(whitespaceRE, s => s.trim());
|
|
370
|
+
let state = 0 /* inMemberExp */;
|
|
371
|
+
let prevState = 0 /* inMemberExp */;
|
|
372
|
+
let currentOpenBracketCount = 0;
|
|
373
|
+
let currentStringType = null;
|
|
374
|
+
for (let i = 0; i < path.length; i++) {
|
|
375
|
+
const char = path.charAt(i);
|
|
376
|
+
switch (state) {
|
|
377
|
+
case 0 /* inMemberExp */:
|
|
378
|
+
if (char === '[') {
|
|
379
|
+
prevState = state;
|
|
380
|
+
state = 1 /* inBrackets */;
|
|
381
|
+
currentOpenBracketCount++;
|
|
382
|
+
}
|
|
383
|
+
else if (!(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)) {
|
|
384
|
+
return false;
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
case 1 /* inBrackets */:
|
|
388
|
+
if (char === `'` || char === `"` || char === '`') {
|
|
389
|
+
prevState = state;
|
|
390
|
+
state = 2 /* inString */;
|
|
391
|
+
currentStringType = char;
|
|
392
|
+
}
|
|
393
|
+
else if (char === `[`) {
|
|
394
|
+
currentOpenBracketCount++;
|
|
395
|
+
}
|
|
396
|
+
else if (char === `]`) {
|
|
397
|
+
if (!--currentOpenBracketCount) {
|
|
398
|
+
state = prevState;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
break;
|
|
402
|
+
case 2 /* inString */:
|
|
403
|
+
if (char === currentStringType) {
|
|
404
|
+
state = prevState;
|
|
405
|
+
currentStringType = null;
|
|
406
|
+
}
|
|
407
|
+
break;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return !currentOpenBracketCount;
|
|
370
411
|
};
|
|
371
412
|
function getInnerRange(loc, offset, length) {
|
|
372
413
|
const source = loc.source.substr(offset, length);
|
|
@@ -937,6 +978,10 @@ function parseElement(context, ancestors) {
|
|
|
937
978
|
const isPreBoundary = context.inPre && !wasInPre;
|
|
938
979
|
const isVPreBoundary = context.inVPre && !wasInVPre;
|
|
939
980
|
if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {
|
|
981
|
+
// #4030 self-closing <pre> tag
|
|
982
|
+
if (context.options.isPreTag(element.tag)) {
|
|
983
|
+
context.inPre = false;
|
|
984
|
+
}
|
|
940
985
|
return element;
|
|
941
986
|
}
|
|
942
987
|
// Children.
|
|
@@ -992,12 +1037,13 @@ function parseTag(context, type, parent) {
|
|
|
992
1037
|
// save current state in case we need to re-parse attributes with v-pre
|
|
993
1038
|
const cursor = getCursor(context);
|
|
994
1039
|
const currentSource = context.source;
|
|
995
|
-
// Attributes.
|
|
996
|
-
let props = parseAttributes(context, type);
|
|
997
1040
|
// check <pre> tag
|
|
998
|
-
|
|
1041
|
+
const isPreTag = context.options.isPreTag(tag);
|
|
1042
|
+
if (isPreTag) {
|
|
999
1043
|
context.inPre = true;
|
|
1000
1044
|
}
|
|
1045
|
+
// Attributes.
|
|
1046
|
+
let props = parseAttributes(context, type);
|
|
1001
1047
|
// check v-pre
|
|
1002
1048
|
if (type === 0 /* Start */ &&
|
|
1003
1049
|
!context.inVPre &&
|
|
@@ -1025,41 +1071,17 @@ function parseTag(context, type, parent) {
|
|
|
1025
1071
|
return;
|
|
1026
1072
|
}
|
|
1027
1073
|
let tagType = 0 /* ELEMENT */;
|
|
1028
|
-
|
|
1029
|
-
if (!context.inVPre && !options.isCustomElement(tag)) {
|
|
1030
|
-
const hasVIs = props.some(p => {
|
|
1031
|
-
if (p.name !== 'is')
|
|
1032
|
-
return;
|
|
1033
|
-
// v-is="xxx" (TODO: deprecate)
|
|
1034
|
-
if (p.type === 7 /* DIRECTIVE */) {
|
|
1035
|
-
return true;
|
|
1036
|
-
}
|
|
1037
|
-
// is="vue:xxx"
|
|
1038
|
-
if (p.value && p.value.content.startsWith('vue:')) {
|
|
1039
|
-
return true;
|
|
1040
|
-
}
|
|
1041
|
-
// in compat mode, any is usage is considered a component
|
|
1042
|
-
if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1043
|
-
return true;
|
|
1044
|
-
}
|
|
1045
|
-
});
|
|
1046
|
-
if (options.isNativeTag && !hasVIs) {
|
|
1047
|
-
if (!options.isNativeTag(tag))
|
|
1048
|
-
tagType = 1 /* COMPONENT */;
|
|
1049
|
-
}
|
|
1050
|
-
else if (hasVIs ||
|
|
1051
|
-
isCoreComponent(tag) ||
|
|
1052
|
-
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
|
1053
|
-
/^[A-Z]/.test(tag) ||
|
|
1054
|
-
tag === 'component') {
|
|
1055
|
-
tagType = 1 /* COMPONENT */;
|
|
1056
|
-
}
|
|
1074
|
+
if (!context.inVPre) {
|
|
1057
1075
|
if (tag === 'slot') {
|
|
1058
1076
|
tagType = 2 /* SLOT */;
|
|
1059
1077
|
}
|
|
1060
|
-
else if (tag === 'template'
|
|
1061
|
-
props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
|
|
1062
|
-
|
|
1078
|
+
else if (tag === 'template') {
|
|
1079
|
+
if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
|
|
1080
|
+
tagType = 3 /* TEMPLATE */;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
else if (isComponent(tag, props, context)) {
|
|
1084
|
+
tagType = 1 /* COMPONENT */;
|
|
1063
1085
|
}
|
|
1064
1086
|
}
|
|
1065
1087
|
return {
|
|
@@ -1074,6 +1096,49 @@ function parseTag(context, type, parent) {
|
|
|
1074
1096
|
codegenNode: undefined // to be created during transform phase
|
|
1075
1097
|
};
|
|
1076
1098
|
}
|
|
1099
|
+
function isComponent(tag, props, context) {
|
|
1100
|
+
const options = context.options;
|
|
1101
|
+
if (options.isCustomElement(tag)) {
|
|
1102
|
+
return false;
|
|
1103
|
+
}
|
|
1104
|
+
if (tag === 'component' ||
|
|
1105
|
+
/^[A-Z]/.test(tag) ||
|
|
1106
|
+
isCoreComponent(tag) ||
|
|
1107
|
+
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
|
1108
|
+
(options.isNativeTag && !options.isNativeTag(tag))) {
|
|
1109
|
+
return true;
|
|
1110
|
+
}
|
|
1111
|
+
// at this point the tag should be a native tag, but check for potential "is"
|
|
1112
|
+
// casting
|
|
1113
|
+
for (let i = 0; i < props.length; i++) {
|
|
1114
|
+
const p = props[i];
|
|
1115
|
+
if (p.type === 6 /* ATTRIBUTE */) {
|
|
1116
|
+
if (p.name === 'is' && p.value) {
|
|
1117
|
+
if (p.value.content.startsWith('vue:')) {
|
|
1118
|
+
return true;
|
|
1119
|
+
}
|
|
1120
|
+
else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1121
|
+
return true;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
}
|
|
1125
|
+
else {
|
|
1126
|
+
// directive
|
|
1127
|
+
// v-is (TODO Deprecate)
|
|
1128
|
+
if (p.name === 'is') {
|
|
1129
|
+
return true;
|
|
1130
|
+
}
|
|
1131
|
+
else if (
|
|
1132
|
+
// :is on plain element - only treat as component in compat mode
|
|
1133
|
+
p.name === 'bind' &&
|
|
1134
|
+
isBindKey(p.arg, 'is') &&
|
|
1135
|
+
true &&
|
|
1136
|
+
checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1137
|
+
return true;
|
|
1138
|
+
}
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1077
1142
|
function parseAttributes(context, type) {
|
|
1078
1143
|
const props = [];
|
|
1079
1144
|
const attributeNames = new Set();
|
|
@@ -1945,7 +2010,7 @@ function createStructuralDirectiveTransform(name, fn) {
|
|
|
1945
2010
|
|
|
1946
2011
|
const PURE_ANNOTATION = `/*#__PURE__*/`;
|
|
1947
2012
|
const WITH_ID = `_withId`;
|
|
1948
|
-
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 }) {
|
|
2013
|
+
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, isTS = false }) {
|
|
1949
2014
|
const context = {
|
|
1950
2015
|
mode,
|
|
1951
2016
|
prefixIdentifiers,
|
|
@@ -1956,6 +2021,7 @@ function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode
|
|
|
1956
2021
|
runtimeGlobalName,
|
|
1957
2022
|
runtimeModuleName,
|
|
1958
2023
|
ssr,
|
|
2024
|
+
isTS,
|
|
1959
2025
|
source: ast.loc.source,
|
|
1960
2026
|
code: ``,
|
|
1961
2027
|
column: 1,
|
|
@@ -2235,7 +2301,7 @@ function genModulePreamble(ast, context, genScopeId, inline) {
|
|
|
2235
2301
|
push(`export `);
|
|
2236
2302
|
}
|
|
2237
2303
|
}
|
|
2238
|
-
function genAssets(assets, type, { helper, push, newline }) {
|
|
2304
|
+
function genAssets(assets, type, { helper, push, newline, isTS }) {
|
|
2239
2305
|
const resolver = helper(type === 'filter'
|
|
2240
2306
|
? RESOLVE_FILTER
|
|
2241
2307
|
: type === 'component'
|
|
@@ -2248,7 +2314,7 @@ function genAssets(assets, type, { helper, push, newline }) {
|
|
|
2248
2314
|
if (maybeSelfReference) {
|
|
2249
2315
|
id = id.slice(0, -6);
|
|
2250
2316
|
}
|
|
2251
|
-
push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`);
|
|
2317
|
+
push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);
|
|
2252
2318
|
if (i < assets.length - 1) {
|
|
2253
2319
|
newline();
|
|
2254
2320
|
}
|
|
@@ -3873,16 +3939,10 @@ function resolveComponentType(node, context, ssr = false) {
|
|
|
3873
3939
|
let { tag } = node;
|
|
3874
3940
|
// 1. dynamic component
|
|
3875
3941
|
const isExplicitDynamic = isComponentTag(tag);
|
|
3876
|
-
const isProp = findProp(node, 'is')
|
|
3942
|
+
const isProp = findProp(node, 'is');
|
|
3877
3943
|
if (isProp) {
|
|
3878
|
-
if (
|
|
3879
|
-
|
|
3880
|
-
// if not <component>, only is value that starts with "vue:" will be
|
|
3881
|
-
// treated as component by the parse phase and reach here, unless it's
|
|
3882
|
-
// compat mode where all is values are considered components
|
|
3883
|
-
tag = isProp.value.content.replace(/^vue:/, '');
|
|
3884
|
-
}
|
|
3885
|
-
else {
|
|
3944
|
+
if (isExplicitDynamic ||
|
|
3945
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {
|
|
3886
3946
|
const exp = isProp.type === 6 /* ATTRIBUTE */
|
|
3887
3947
|
? isProp.value && createSimpleExpression(isProp.value.content, true)
|
|
3888
3948
|
: isProp.exp;
|
|
@@ -3892,6 +3952,21 @@ function resolveComponentType(node, context, ssr = false) {
|
|
|
3892
3952
|
]);
|
|
3893
3953
|
}
|
|
3894
3954
|
}
|
|
3955
|
+
else if (isProp.type === 6 /* ATTRIBUTE */ &&
|
|
3956
|
+
isProp.value.content.startsWith('vue:')) {
|
|
3957
|
+
// <button is="vue:xxx">
|
|
3958
|
+
// if not <component>, only is value that starts with "vue:" will be
|
|
3959
|
+
// treated as component by the parse phase and reach here, unless it's
|
|
3960
|
+
// compat mode where all is values are considered components
|
|
3961
|
+
tag = isProp.value.content.slice(4);
|
|
3962
|
+
}
|
|
3963
|
+
}
|
|
3964
|
+
// 1.5 v-is (TODO: Deprecate)
|
|
3965
|
+
const isDir = !isExplicitDynamic && findDir(node, 'is');
|
|
3966
|
+
if (isDir && isDir.exp) {
|
|
3967
|
+
return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
|
|
3968
|
+
isDir.exp
|
|
3969
|
+
]);
|
|
3895
3970
|
}
|
|
3896
3971
|
// 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
|
|
3897
3972
|
const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);
|
|
@@ -4035,7 +4110,9 @@ function buildProps(node, context, props = node.props, ssr = false) {
|
|
|
4035
4110
|
}
|
|
4036
4111
|
// skip is on <component>, or is="vue:xxx"
|
|
4037
4112
|
if (name === 'is' &&
|
|
4038
|
-
(isComponentTag(tag) ||
|
|
4113
|
+
(isComponentTag(tag) ||
|
|
4114
|
+
(value && value.content.startsWith('vue:')) ||
|
|
4115
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {
|
|
4039
4116
|
continue;
|
|
4040
4117
|
}
|
|
4041
4118
|
properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
|
|
@@ -4058,7 +4135,10 @@ function buildProps(node, context, props = node.props, ssr = false) {
|
|
|
4058
4135
|
}
|
|
4059
4136
|
// skip v-is and :is on <component>
|
|
4060
4137
|
if (name === 'is' ||
|
|
4061
|
-
(isVBind &&
|
|
4138
|
+
(isVBind &&
|
|
4139
|
+
isBindKey(arg, 'is') &&
|
|
4140
|
+
(isComponentTag(tag) ||
|
|
4141
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {
|
|
4062
4142
|
continue;
|
|
4063
4143
|
}
|
|
4064
4144
|
// skip v-on in SSR compilation
|
|
@@ -4219,7 +4299,7 @@ function buildDirectiveArgs(dir, context) {
|
|
|
4219
4299
|
else {
|
|
4220
4300
|
// user directive.
|
|
4221
4301
|
// see if we have directives exposed via <script setup>
|
|
4222
|
-
const fromSetup = resolveSetupReference(dir.name, context);
|
|
4302
|
+
const fromSetup = resolveSetupReference('v-' + dir.name, context);
|
|
4223
4303
|
if (fromSetup) {
|
|
4224
4304
|
dirArgs.push(fromSetup);
|
|
4225
4305
|
}
|
|
@@ -4616,7 +4696,7 @@ const transformModel = (dir, node, context) => {
|
|
|
4616
4696
|
const maybeRef = context.inline &&
|
|
4617
4697
|
bindingType &&
|
|
4618
4698
|
bindingType !== "setup-const" /* SETUP_CONST */;
|
|
4619
|
-
if (!isMemberExpression(expString) && !maybeRef) {
|
|
4699
|
+
if (!expString.trim() || (!isMemberExpression(expString) && !maybeRef)) {
|
|
4620
4700
|
context.onError(createCompilerError(41 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));
|
|
4621
4701
|
return createTransformProps();
|
|
4622
4702
|
}
|
package/dist/compiler-core.d.ts
CHANGED
|
@@ -119,7 +119,7 @@ export declare const CAPITALIZE: unique symbol;
|
|
|
119
119
|
|
|
120
120
|
export declare function checkCompatEnabled(key: CompilerDeprecationTypes, context: ParserContext | TransformContext, loc: SourceLocation | null, ...args: any[]): boolean;
|
|
121
121
|
|
|
122
|
-
export declare interface CodegenContext extends Omit<Required<CodegenOptions>, 'bindingMetadata' | 'inline'
|
|
122
|
+
export declare interface CodegenContext extends Omit<Required<CodegenOptions>, 'bindingMetadata' | 'inline'> {
|
|
123
123
|
source: string;
|
|
124
124
|
code: string;
|
|
125
125
|
line: number;
|
|
@@ -557,6 +557,12 @@ export declare const isBuiltInType: (tag: string, expected: string) => boolean;
|
|
|
557
557
|
|
|
558
558
|
export declare function isCoreComponent(tag: string): symbol | void;
|
|
559
559
|
|
|
560
|
+
/**
|
|
561
|
+
* Simple lexer to check if an expression is a member expression. This is
|
|
562
|
+
* lax and only checks validity at the root level (i.e. does not validate exps
|
|
563
|
+
* inside square brackets), but it's ok since these are only used on template
|
|
564
|
+
* expressions and false positives are invalid expressions in the first place.
|
|
565
|
+
*/
|
|
560
566
|
export declare const isMemberExpression: (path: string) => boolean;
|
|
561
567
|
|
|
562
568
|
export declare const isSimpleIdentifier: (name: string) => boolean;
|
|
@@ -351,18 +351,59 @@ function isCoreComponent(tag) {
|
|
|
351
351
|
}
|
|
352
352
|
const nonIdentifierRE = /^\d|[^\$\w]/;
|
|
353
353
|
const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
|
|
354
|
-
const
|
|
354
|
+
const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/;
|
|
355
|
+
const validIdentCharRE = /[\.\w$\xA0-\uFFFF]/;
|
|
356
|
+
const whitespaceRE = /\s+[.[]\s*|\s*[.[]\s+/g;
|
|
357
|
+
/**
|
|
358
|
+
* Simple lexer to check if an expression is a member expression. This is
|
|
359
|
+
* lax and only checks validity at the root level (i.e. does not validate exps
|
|
360
|
+
* inside square brackets), but it's ok since these are only used on template
|
|
361
|
+
* expressions and false positives are invalid expressions in the first place.
|
|
362
|
+
*/
|
|
355
363
|
const isMemberExpression = (path) => {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
364
|
+
// remove whitespaces around . or [ first
|
|
365
|
+
path = path.trim().replace(whitespaceRE, s => s.trim());
|
|
366
|
+
let state = 0 /* inMemberExp */;
|
|
367
|
+
let prevState = 0 /* inMemberExp */;
|
|
368
|
+
let currentOpenBracketCount = 0;
|
|
369
|
+
let currentStringType = null;
|
|
370
|
+
for (let i = 0; i < path.length; i++) {
|
|
371
|
+
const char = path.charAt(i);
|
|
372
|
+
switch (state) {
|
|
373
|
+
case 0 /* inMemberExp */:
|
|
374
|
+
if (char === '[') {
|
|
375
|
+
prevState = state;
|
|
376
|
+
state = 1 /* inBrackets */;
|
|
377
|
+
currentOpenBracketCount++;
|
|
378
|
+
}
|
|
379
|
+
else if (!(i === 0 ? validFirstIdentCharRE : validIdentCharRE).test(char)) {
|
|
380
|
+
return false;
|
|
381
|
+
}
|
|
382
|
+
break;
|
|
383
|
+
case 1 /* inBrackets */:
|
|
384
|
+
if (char === `'` || char === `"` || char === '`') {
|
|
385
|
+
prevState = state;
|
|
386
|
+
state = 2 /* inString */;
|
|
387
|
+
currentStringType = char;
|
|
388
|
+
}
|
|
389
|
+
else if (char === `[`) {
|
|
390
|
+
currentOpenBracketCount++;
|
|
391
|
+
}
|
|
392
|
+
else if (char === `]`) {
|
|
393
|
+
if (!--currentOpenBracketCount) {
|
|
394
|
+
state = prevState;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
break;
|
|
398
|
+
case 2 /* inString */:
|
|
399
|
+
if (char === currentStringType) {
|
|
400
|
+
state = prevState;
|
|
401
|
+
currentStringType = null;
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
return !currentOpenBracketCount;
|
|
366
407
|
};
|
|
367
408
|
function getInnerRange(loc, offset, length) {
|
|
368
409
|
const source = loc.source.substr(offset, length);
|
|
@@ -940,6 +981,10 @@ function parseElement(context, ancestors) {
|
|
|
940
981
|
const isPreBoundary = context.inPre && !wasInPre;
|
|
941
982
|
const isVPreBoundary = context.inVPre && !wasInVPre;
|
|
942
983
|
if (element.isSelfClosing || context.options.isVoidTag(element.tag)) {
|
|
984
|
+
// #4030 self-closing <pre> tag
|
|
985
|
+
if (context.options.isPreTag(element.tag)) {
|
|
986
|
+
context.inPre = false;
|
|
987
|
+
}
|
|
943
988
|
return element;
|
|
944
989
|
}
|
|
945
990
|
// Children.
|
|
@@ -995,12 +1040,13 @@ function parseTag(context, type, parent) {
|
|
|
995
1040
|
// save current state in case we need to re-parse attributes with v-pre
|
|
996
1041
|
const cursor = getCursor(context);
|
|
997
1042
|
const currentSource = context.source;
|
|
998
|
-
// Attributes.
|
|
999
|
-
let props = parseAttributes(context, type);
|
|
1000
1043
|
// check <pre> tag
|
|
1001
|
-
|
|
1044
|
+
const isPreTag = context.options.isPreTag(tag);
|
|
1045
|
+
if (isPreTag) {
|
|
1002
1046
|
context.inPre = true;
|
|
1003
1047
|
}
|
|
1048
|
+
// Attributes.
|
|
1049
|
+
let props = parseAttributes(context, type);
|
|
1004
1050
|
// check v-pre
|
|
1005
1051
|
if (type === 0 /* Start */ &&
|
|
1006
1052
|
!context.inVPre &&
|
|
@@ -1048,41 +1094,17 @@ function parseTag(context, type, parent) {
|
|
|
1048
1094
|
}
|
|
1049
1095
|
}
|
|
1050
1096
|
let tagType = 0 /* ELEMENT */;
|
|
1051
|
-
|
|
1052
|
-
if (!context.inVPre && !options.isCustomElement(tag)) {
|
|
1053
|
-
const hasVIs = props.some(p => {
|
|
1054
|
-
if (p.name !== 'is')
|
|
1055
|
-
return;
|
|
1056
|
-
// v-is="xxx" (TODO: deprecate)
|
|
1057
|
-
if (p.type === 7 /* DIRECTIVE */) {
|
|
1058
|
-
return true;
|
|
1059
|
-
}
|
|
1060
|
-
// is="vue:xxx"
|
|
1061
|
-
if (p.value && p.value.content.startsWith('vue:')) {
|
|
1062
|
-
return true;
|
|
1063
|
-
}
|
|
1064
|
-
// in compat mode, any is usage is considered a component
|
|
1065
|
-
if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1066
|
-
return true;
|
|
1067
|
-
}
|
|
1068
|
-
});
|
|
1069
|
-
if (options.isNativeTag && !hasVIs) {
|
|
1070
|
-
if (!options.isNativeTag(tag))
|
|
1071
|
-
tagType = 1 /* COMPONENT */;
|
|
1072
|
-
}
|
|
1073
|
-
else if (hasVIs ||
|
|
1074
|
-
isCoreComponent(tag) ||
|
|
1075
|
-
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
|
1076
|
-
/^[A-Z]/.test(tag) ||
|
|
1077
|
-
tag === 'component') {
|
|
1078
|
-
tagType = 1 /* COMPONENT */;
|
|
1079
|
-
}
|
|
1097
|
+
if (!context.inVPre) {
|
|
1080
1098
|
if (tag === 'slot') {
|
|
1081
1099
|
tagType = 2 /* SLOT */;
|
|
1082
1100
|
}
|
|
1083
|
-
else if (tag === 'template'
|
|
1084
|
-
props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
|
|
1085
|
-
|
|
1101
|
+
else if (tag === 'template') {
|
|
1102
|
+
if (props.some(p => p.type === 7 /* DIRECTIVE */ && isSpecialTemplateDirective(p.name))) {
|
|
1103
|
+
tagType = 3 /* TEMPLATE */;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
else if (isComponent(tag, props, context)) {
|
|
1107
|
+
tagType = 1 /* COMPONENT */;
|
|
1086
1108
|
}
|
|
1087
1109
|
}
|
|
1088
1110
|
return {
|
|
@@ -1097,6 +1119,49 @@ function parseTag(context, type, parent) {
|
|
|
1097
1119
|
codegenNode: undefined // to be created during transform phase
|
|
1098
1120
|
};
|
|
1099
1121
|
}
|
|
1122
|
+
function isComponent(tag, props, context) {
|
|
1123
|
+
const options = context.options;
|
|
1124
|
+
if (options.isCustomElement(tag)) {
|
|
1125
|
+
return false;
|
|
1126
|
+
}
|
|
1127
|
+
if (tag === 'component' ||
|
|
1128
|
+
/^[A-Z]/.test(tag) ||
|
|
1129
|
+
isCoreComponent(tag) ||
|
|
1130
|
+
(options.isBuiltInComponent && options.isBuiltInComponent(tag)) ||
|
|
1131
|
+
(options.isNativeTag && !options.isNativeTag(tag))) {
|
|
1132
|
+
return true;
|
|
1133
|
+
}
|
|
1134
|
+
// at this point the tag should be a native tag, but check for potential "is"
|
|
1135
|
+
// casting
|
|
1136
|
+
for (let i = 0; i < props.length; i++) {
|
|
1137
|
+
const p = props[i];
|
|
1138
|
+
if (p.type === 6 /* ATTRIBUTE */) {
|
|
1139
|
+
if (p.name === 'is' && p.value) {
|
|
1140
|
+
if (p.value.content.startsWith('vue:')) {
|
|
1141
|
+
return true;
|
|
1142
|
+
}
|
|
1143
|
+
else if (checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1144
|
+
return true;
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
else {
|
|
1149
|
+
// directive
|
|
1150
|
+
// v-is (TODO Deprecate)
|
|
1151
|
+
if (p.name === 'is') {
|
|
1152
|
+
return true;
|
|
1153
|
+
}
|
|
1154
|
+
else if (
|
|
1155
|
+
// :is on plain element - only treat as component in compat mode
|
|
1156
|
+
p.name === 'bind' &&
|
|
1157
|
+
isBindKey(p.arg, 'is') &&
|
|
1158
|
+
true &&
|
|
1159
|
+
checkCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context, p.loc)) {
|
|
1160
|
+
return true;
|
|
1161
|
+
}
|
|
1162
|
+
}
|
|
1163
|
+
}
|
|
1164
|
+
}
|
|
1100
1165
|
function parseAttributes(context, type) {
|
|
1101
1166
|
const props = [];
|
|
1102
1167
|
const attributeNames = new Set();
|
|
@@ -1961,7 +2026,7 @@ function createStructuralDirectiveTransform(name, fn) {
|
|
|
1961
2026
|
}
|
|
1962
2027
|
|
|
1963
2028
|
const PURE_ANNOTATION = `/*#__PURE__*/`;
|
|
1964
|
-
function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode === 'module', sourceMap = false, filename = `template.vue.html`, scopeId = null, optimizeImports = false, runtimeGlobalName = `Vue`, runtimeModuleName = `vue`, ssr = false }) {
|
|
2029
|
+
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 }) {
|
|
1965
2030
|
const context = {
|
|
1966
2031
|
mode,
|
|
1967
2032
|
prefixIdentifiers,
|
|
@@ -1972,6 +2037,7 @@ function createCodegenContext(ast, { mode = 'function', prefixIdentifiers = mode
|
|
|
1972
2037
|
runtimeGlobalName,
|
|
1973
2038
|
runtimeModuleName,
|
|
1974
2039
|
ssr,
|
|
2040
|
+
isTS,
|
|
1975
2041
|
source: ast.loc.source,
|
|
1976
2042
|
code: ``,
|
|
1977
2043
|
column: 1,
|
|
@@ -2127,7 +2193,7 @@ function genFunctionPreamble(ast, context) {
|
|
|
2127
2193
|
newline();
|
|
2128
2194
|
push(`return `);
|
|
2129
2195
|
}
|
|
2130
|
-
function genAssets(assets, type, { helper, push, newline }) {
|
|
2196
|
+
function genAssets(assets, type, { helper, push, newline, isTS }) {
|
|
2131
2197
|
const resolver = helper(type === 'filter'
|
|
2132
2198
|
? RESOLVE_FILTER
|
|
2133
2199
|
: type === 'component'
|
|
@@ -2140,7 +2206,7 @@ function genAssets(assets, type, { helper, push, newline }) {
|
|
|
2140
2206
|
if (maybeSelfReference) {
|
|
2141
2207
|
id = id.slice(0, -6);
|
|
2142
2208
|
}
|
|
2143
|
-
push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})`);
|
|
2209
|
+
push(`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${maybeSelfReference ? `, true` : ``})${isTS ? `!` : ``}`);
|
|
2144
2210
|
if (i < assets.length - 1) {
|
|
2145
2211
|
newline();
|
|
2146
2212
|
}
|
|
@@ -3420,16 +3486,10 @@ function resolveComponentType(node, context, ssr = false) {
|
|
|
3420
3486
|
let { tag } = node;
|
|
3421
3487
|
// 1. dynamic component
|
|
3422
3488
|
const isExplicitDynamic = isComponentTag(tag);
|
|
3423
|
-
const isProp = findProp(node, 'is')
|
|
3489
|
+
const isProp = findProp(node, 'is');
|
|
3424
3490
|
if (isProp) {
|
|
3425
|
-
if (
|
|
3426
|
-
|
|
3427
|
-
// if not <component>, only is value that starts with "vue:" will be
|
|
3428
|
-
// treated as component by the parse phase and reach here, unless it's
|
|
3429
|
-
// compat mode where all is values are considered components
|
|
3430
|
-
tag = isProp.value.content.replace(/^vue:/, '');
|
|
3431
|
-
}
|
|
3432
|
-
else {
|
|
3491
|
+
if (isExplicitDynamic ||
|
|
3492
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))) {
|
|
3433
3493
|
const exp = isProp.type === 6 /* ATTRIBUTE */
|
|
3434
3494
|
? isProp.value && createSimpleExpression(isProp.value.content, true)
|
|
3435
3495
|
: isProp.exp;
|
|
@@ -3439,6 +3499,21 @@ function resolveComponentType(node, context, ssr = false) {
|
|
|
3439
3499
|
]);
|
|
3440
3500
|
}
|
|
3441
3501
|
}
|
|
3502
|
+
else if (isProp.type === 6 /* ATTRIBUTE */ &&
|
|
3503
|
+
isProp.value.content.startsWith('vue:')) {
|
|
3504
|
+
// <button is="vue:xxx">
|
|
3505
|
+
// if not <component>, only is value that starts with "vue:" will be
|
|
3506
|
+
// treated as component by the parse phase and reach here, unless it's
|
|
3507
|
+
// compat mode where all is values are considered components
|
|
3508
|
+
tag = isProp.value.content.slice(4);
|
|
3509
|
+
}
|
|
3510
|
+
}
|
|
3511
|
+
// 1.5 v-is (TODO: Deprecate)
|
|
3512
|
+
const isDir = !isExplicitDynamic && findDir(node, 'is');
|
|
3513
|
+
if (isDir && isDir.exp) {
|
|
3514
|
+
return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
|
|
3515
|
+
isDir.exp
|
|
3516
|
+
]);
|
|
3442
3517
|
}
|
|
3443
3518
|
// 2. built-in components (Teleport, Transition, KeepAlive, Suspense...)
|
|
3444
3519
|
const builtIn = isCoreComponent(tag) || context.isBuiltInComponent(tag);
|
|
@@ -3522,7 +3597,9 @@ function buildProps(node, context, props = node.props, ssr = false) {
|
|
|
3522
3597
|
}
|
|
3523
3598
|
// skip is on <component>, or is="vue:xxx"
|
|
3524
3599
|
if (name === 'is' &&
|
|
3525
|
-
(isComponentTag(tag) ||
|
|
3600
|
+
(isComponentTag(tag) ||
|
|
3601
|
+
(value && value.content.startsWith('vue:')) ||
|
|
3602
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context)))) {
|
|
3526
3603
|
continue;
|
|
3527
3604
|
}
|
|
3528
3605
|
properties.push(createObjectProperty(createSimpleExpression(name, true, getInnerRange(loc, 0, name.length)), createSimpleExpression(value ? value.content : '', isStatic, value ? value.loc : loc)));
|
|
@@ -3545,7 +3622,10 @@ function buildProps(node, context, props = node.props, ssr = false) {
|
|
|
3545
3622
|
}
|
|
3546
3623
|
// skip v-is and :is on <component>
|
|
3547
3624
|
if (name === 'is' ||
|
|
3548
|
-
(isVBind &&
|
|
3625
|
+
(isVBind &&
|
|
3626
|
+
isBindKey(arg, 'is') &&
|
|
3627
|
+
(isComponentTag(tag) ||
|
|
3628
|
+
(isCompatEnabled("COMPILER_IS_ON_ELEMENT" /* COMPILER_IS_ON_ELEMENT */, context))))) {
|
|
3549
3629
|
continue;
|
|
3550
3630
|
}
|
|
3551
3631
|
// skip v-on in SSR compilation
|
|
@@ -4089,7 +4169,7 @@ const transformModel = (dir, node, context) => {
|
|
|
4089
4169
|
// _unref(exp)
|
|
4090
4170
|
context.bindingMetadata[rawExp];
|
|
4091
4171
|
const maybeRef = !true /* SETUP_CONST */;
|
|
4092
|
-
if (!isMemberExpression(expString) && !maybeRef) {
|
|
4172
|
+
if (!expString.trim() || (!isMemberExpression(expString) && !maybeRef)) {
|
|
4093
4173
|
context.onError(createCompilerError(41 /* X_V_MODEL_MALFORMED_EXPRESSION */, exp.loc));
|
|
4094
4174
|
return createTransformProps();
|
|
4095
4175
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vue/compiler-core",
|
|
3
|
-
"version": "3.1.
|
|
3
|
+
"version": "3.1.4",
|
|
4
4
|
"description": "@vue/compiler-core",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"module": "dist/compiler-core.esm-bundler.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"homepage": "https://github.com/vuejs/vue-next/tree/master/packages/compiler-core#readme",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@vue/shared": "3.1.
|
|
35
|
+
"@vue/shared": "3.1.4",
|
|
36
36
|
"@babel/parser": "^7.12.0",
|
|
37
37
|
"@babel/types": "^7.12.0",
|
|
38
38
|
"estree-walker": "^2.0.1",
|