@vue-jsx-vapor/compiler 2.6.4 → 2.6.7
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/index.cjs +629 -287
- package/dist/index.d.cts +80 -22
- package/dist/index.d.ts +80 -22
- package/dist/index.js +594 -252
- package/package.json +4 -3
package/dist/index.js
CHANGED
@@ -1,10 +1,63 @@
|
|
1
1
|
import { parse, parseExpression } from "@babel/parser";
|
2
|
-
import { NOOP, camelize, canSetValueDirectly, capitalize, extend, isArray, isBuiltInDirective, isGloballyAllowed, isHTMLTag, isSVGTag, isString, isVoidTag, makeMap, remove, shouldSetAsAttr, toHandlerKey } from "@vue/shared";
|
3
|
-
import { DOMErrorCodes, ErrorCodes, NewlineType, NodeTypes, TS_NODE_TYPES, advancePositionWithClone, advancePositionWithMutation, createCompilerError, createDOMCompilerError, createSimpleExpression, defaultOnError, defaultOnWarn, isConstantNode, isFnExpression, isLiteralWhitelisted, isMemberExpression, isSimpleIdentifier, isStaticProperty, isValidHTMLNesting, locStub, resolveModifiers, toValidAssetId, unwrapTSNode, walkIdentifiers } from "@vue/compiler-dom";
|
4
|
-
import { walkAST, walkIdentifiers as walkIdentifiers$1 } from "ast-kit";
|
5
|
-
import { isNodesEquivalent, jsxClosingFragment, jsxExpressionContainer, jsxFragment, jsxOpeningFragment } from "@babel/types";
|
2
|
+
import { NOOP, camelize, canSetValueDirectly, capitalize, escapeHtml, extend, isArray, isBuiltInDirective, isGloballyAllowed, isHTMLTag, isSVGTag, isString, isVoidTag, makeMap, remove, shouldSetAsAttr, toHandlerKey } from "@vue/shared";
|
6
3
|
import { SourceMapGenerator } from "source-map-js";
|
4
|
+
import { walkAST, walkIdentifiers } from "ast-kit";
|
7
5
|
|
6
|
+
//#region src/utils/error.ts
|
7
|
+
let ErrorCodes = /* @__PURE__ */ function(ErrorCodes$1) {
|
8
|
+
ErrorCodes$1[ErrorCodes$1["X_V_IF_NO_EXPRESSION"] = 28] = "X_V_IF_NO_EXPRESSION";
|
9
|
+
ErrorCodes$1[ErrorCodes$1["X_V_ELSE_NO_ADJACENT_IF"] = 30] = "X_V_ELSE_NO_ADJACENT_IF";
|
10
|
+
ErrorCodes$1[ErrorCodes$1["X_V_FOR_NO_EXPRESSION"] = 31] = "X_V_FOR_NO_EXPRESSION";
|
11
|
+
ErrorCodes$1[ErrorCodes$1["X_V_FOR_MALFORMED_EXPRESSION"] = 32] = "X_V_FOR_MALFORMED_EXPRESSION";
|
12
|
+
ErrorCodes$1[ErrorCodes$1["X_V_ON_NO_EXPRESSION"] = 35] = "X_V_ON_NO_EXPRESSION";
|
13
|
+
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_MIXED_SLOT_USAGE"] = 37] = "X_V_SLOT_MIXED_SLOT_USAGE";
|
14
|
+
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_DUPLICATE_SLOT_NAMES"] = 38] = "X_V_SLOT_DUPLICATE_SLOT_NAMES";
|
15
|
+
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN"] = 39] = "X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN";
|
16
|
+
ErrorCodes$1[ErrorCodes$1["X_V_SLOT_MISPLACED"] = 40] = "X_V_SLOT_MISPLACED";
|
17
|
+
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_NO_EXPRESSION"] = 41] = "X_V_MODEL_NO_EXPRESSION";
|
18
|
+
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_MALFORMED_EXPRESSION"] = 42] = "X_V_MODEL_MALFORMED_EXPRESSION";
|
19
|
+
ErrorCodes$1[ErrorCodes$1["X_V_HTML_NO_EXPRESSION"] = 53] = "X_V_HTML_NO_EXPRESSION";
|
20
|
+
ErrorCodes$1[ErrorCodes$1["X_V_HTML_WITH_CHILDREN"] = 54] = "X_V_HTML_WITH_CHILDREN";
|
21
|
+
ErrorCodes$1[ErrorCodes$1["X_V_TEXT_NO_EXPRESSION"] = 55] = "X_V_TEXT_NO_EXPRESSION";
|
22
|
+
ErrorCodes$1[ErrorCodes$1["X_V_TEXT_WITH_CHILDREN"] = 56] = "X_V_TEXT_WITH_CHILDREN";
|
23
|
+
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_ON_INVALID_ELEMENT"] = 57] = "X_V_MODEL_ON_INVALID_ELEMENT";
|
24
|
+
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_ARG_ON_ELEMENT"] = 58] = "X_V_MODEL_ARG_ON_ELEMENT";
|
25
|
+
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_ON_FILE_INPUT_ELEMENT"] = 59] = "X_V_MODEL_ON_FILE_INPUT_ELEMENT";
|
26
|
+
ErrorCodes$1[ErrorCodes$1["X_V_MODEL_UNNECESSARY_VALUE"] = 60] = "X_V_MODEL_UNNECESSARY_VALUE";
|
27
|
+
ErrorCodes$1[ErrorCodes$1["X_V_SHOW_NO_EXPRESSION"] = 61] = "X_V_SHOW_NO_EXPRESSION";
|
28
|
+
return ErrorCodes$1;
|
29
|
+
}({});
|
30
|
+
const errorMessages = {
|
31
|
+
[ErrorCodes.X_V_IF_NO_EXPRESSION]: `v-if/v-else-if is missing expression.`,
|
32
|
+
[ErrorCodes.X_V_ELSE_NO_ADJACENT_IF]: `v-else/v-else-if has no adjacent v-if or v-else-if.`,
|
33
|
+
[ErrorCodes.X_V_FOR_NO_EXPRESSION]: `v-for is missing expression.`,
|
34
|
+
[ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION]: `v-for has invalid expression.`,
|
35
|
+
[ErrorCodes.X_V_ON_NO_EXPRESSION]: `v-on is missing expression.`,
|
36
|
+
[ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE]: "Mixed v-slot usage on both the component and nested <template>. When there are multiple named slots, all slots should use <template> syntax to avoid scope ambiguity.",
|
37
|
+
[ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES]: `Duplicate slot names found. `,
|
38
|
+
[ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN]: "Extraneous children found when component already has explicitly named default slot. These children will be ignored.",
|
39
|
+
[ErrorCodes.X_V_MODEL_NO_EXPRESSION]: `v-model is missing expression.`,
|
40
|
+
[ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION]: `v-model value must be a valid JavaScript member expression.`,
|
41
|
+
[ErrorCodes.X_V_SLOT_MISPLACED]: `v-slot can only be used on components or <template> tags.`,
|
42
|
+
[ErrorCodes.X_V_HTML_NO_EXPRESSION]: `v-html is missing expression.`,
|
43
|
+
[ErrorCodes.X_V_HTML_WITH_CHILDREN]: `v-html will override element children.`,
|
44
|
+
[ErrorCodes.X_V_TEXT_NO_EXPRESSION]: `v-text is missing expression.`,
|
45
|
+
[ErrorCodes.X_V_TEXT_WITH_CHILDREN]: `v-text will override element children.`,
|
46
|
+
[ErrorCodes.X_V_MODEL_ARG_ON_ELEMENT]: `v-model argument is not supported on plain elements.`,
|
47
|
+
[ErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT]: `v-model can only be used on <input>, <textarea> and <select> elements.`,
|
48
|
+
[ErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT]: `v-model cannot be used on file inputs since they are read-only. Use a v-on:change listener instead.`,
|
49
|
+
[ErrorCodes.X_V_MODEL_UNNECESSARY_VALUE]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,
|
50
|
+
[ErrorCodes.X_V_SHOW_NO_EXPRESSION]: `v-show is missing expression.`
|
51
|
+
};
|
52
|
+
function createCompilerError(code, loc, messages, additionalMessage) {
|
53
|
+
const msg = (messages || errorMessages)[code] + (additionalMessage || ``);
|
54
|
+
const error = new SyntaxError(String(msg));
|
55
|
+
error.code = code;
|
56
|
+
error.loc = loc;
|
57
|
+
return error;
|
58
|
+
}
|
59
|
+
|
60
|
+
//#endregion
|
8
61
|
//#region src/ir/component.ts
|
9
62
|
let IRDynamicPropsKind = /* @__PURE__ */ function(IRDynamicPropsKind$1) {
|
10
63
|
IRDynamicPropsKind$1[IRDynamicPropsKind$1["EXPRESSION"] = 0] = "EXPRESSION";
|
@@ -67,62 +120,104 @@ function isBlockOperation(op) {
|
|
67
120
|
}
|
68
121
|
|
69
122
|
//#endregion
|
70
|
-
//#region src/
|
71
|
-
function
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
}
|
76
|
-
}
|
77
|
-
function newBlock(node) {
|
78
|
-
return {
|
79
|
-
type: 1,
|
80
|
-
node,
|
81
|
-
dynamic: newDynamic(),
|
82
|
-
effect: [],
|
83
|
-
operation: [],
|
84
|
-
returns: [],
|
85
|
-
tempId: 0
|
86
|
-
};
|
123
|
+
//#region src/utils/ast.ts
|
124
|
+
function findProp(expression, key) {
|
125
|
+
if (expression?.type === "JSXElement") for (const attr of expression.openingElement.attributes) {
|
126
|
+
const name = attr.type === "JSXAttribute" && (attr.name.type === "JSXIdentifier" ? attr.name.name : attr.name.type === "JSXNamespacedName" ? attr.name.namespace.name : "").split("_")[0];
|
127
|
+
if (name && (isString(key) ? name === key : key.test(name))) return attr;
|
128
|
+
}
|
87
129
|
}
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
130
|
+
const TS_NODE_TYPES = [
|
131
|
+
"TSAsExpression",
|
132
|
+
"TSTypeAssertion",
|
133
|
+
"TSNonNullExpression",
|
134
|
+
"TSInstantiationExpression",
|
135
|
+
"TSSatisfiesExpression"
|
136
|
+
];
|
137
|
+
function unwrapTSNode(node) {
|
138
|
+
if (TS_NODE_TYPES.includes(node.type)) return unwrapTSNode(node.expression);
|
139
|
+
else return node;
|
94
140
|
}
|
95
|
-
function
|
96
|
-
if (node.type
|
97
|
-
|
141
|
+
function isJSXComponent(node) {
|
142
|
+
if (node.type !== "JSXElement") return false;
|
143
|
+
const { openingElement } = node;
|
144
|
+
if (openingElement.name.type === "JSXIdentifier") {
|
145
|
+
const name = openingElement.name.name;
|
146
|
+
return !isHTMLTag(name) && !isSVGTag(name);
|
147
|
+
} else return openingElement.name.type === "JSXMemberExpression";
|
98
148
|
}
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
//#region src/utils.ts
|
104
|
-
function propToExpression(prop, context) {
|
105
|
-
return prop.type === "JSXAttribute" && prop.value?.type === "JSXExpressionContainer" ? resolveExpression(prop.value.expression, context) : EMPTY_EXPRESSION;
|
149
|
+
function isMemberExpression(exp) {
|
150
|
+
if (!exp.ast) return;
|
151
|
+
const ret = unwrapTSNode(exp.ast);
|
152
|
+
return ret.type === "MemberExpression" || ret.type === "OptionalMemberExpression" || ret.type === "Identifier" && ret.name !== "undefined";
|
106
153
|
}
|
107
|
-
function
|
108
|
-
|
154
|
+
function isTemplate(node) {
|
155
|
+
if (node.type === "JSXElement" && node.openingElement.name.type === "JSXIdentifier") return node.openingElement.name.name === "template";
|
109
156
|
}
|
110
|
-
function
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
157
|
+
function isStaticNode(node) {
|
158
|
+
node = unwrapTSNode(node);
|
159
|
+
switch (node.type) {
|
160
|
+
case "UnaryExpression": return isStaticNode(node.argument);
|
161
|
+
case "LogicalExpression":
|
162
|
+
case "BinaryExpression": return isStaticNode(node.left) && isStaticNode(node.right);
|
163
|
+
case "ConditionalExpression": return isStaticNode(node.test) && isStaticNode(node.consequent) && isStaticNode(node.alternate);
|
164
|
+
case "SequenceExpression":
|
165
|
+
case "TemplateLiteral": return node.expressions.every((expr) => isStaticNode(expr));
|
166
|
+
case "ParenthesizedExpression": return isStaticNode(node.expression);
|
167
|
+
case "StringLiteral":
|
168
|
+
case "NumericLiteral":
|
169
|
+
case "BooleanLiteral":
|
170
|
+
case "NullLiteral":
|
171
|
+
case "BigIntLiteral": return true;
|
172
|
+
}
|
173
|
+
return false;
|
174
|
+
}
|
175
|
+
function isConstantNode(node) {
|
176
|
+
if (isStaticNode(node)) return true;
|
177
|
+
node = unwrapTSNode(node);
|
178
|
+
switch (node.type) {
|
179
|
+
case "Identifier": return node.name === "undefined" || isGloballyAllowed(node.name);
|
180
|
+
case "RegExpLiteral": return true;
|
181
|
+
case "ObjectExpression": return node.properties.every((prop) => {
|
182
|
+
if (prop.type === "ObjectMethod") return false;
|
183
|
+
if (prop.type === "SpreadElement") return isConstantNode(prop.argument);
|
184
|
+
return (!prop.computed || isConstantNode(prop.key)) && isConstantNode(prop.value);
|
185
|
+
});
|
186
|
+
case "ArrayExpression": return node.elements.every((element) => {
|
187
|
+
if (element === null) return true;
|
188
|
+
if (element.type === "SpreadElement") return isConstantNode(element.argument);
|
189
|
+
return isConstantNode(element);
|
190
|
+
});
|
118
191
|
}
|
119
|
-
return
|
192
|
+
return false;
|
120
193
|
}
|
121
|
-
const
|
122
|
-
|
123
|
-
|
124
|
-
|
194
|
+
const isFnExpression = (exp) => {
|
195
|
+
try {
|
196
|
+
if (!exp.ast) return false;
|
197
|
+
let ret = exp.ast;
|
198
|
+
if (ret.type === "Program") {
|
199
|
+
ret = ret.body[0];
|
200
|
+
if (ret.type === "ExpressionStatement") ret = ret.expression;
|
201
|
+
}
|
202
|
+
ret = unwrapTSNode(ret);
|
203
|
+
return ret.type === "FunctionExpression" || ret.type === "ArrowFunctionExpression";
|
204
|
+
} catch {
|
205
|
+
return false;
|
206
|
+
}
|
125
207
|
};
|
208
|
+
const isFragmentNode = (node) => node.type === IRNodeTypes.ROOT || node.type === "JSXFragment" || node.type === "JSXElement" && !!isTemplate(node);
|
209
|
+
const isStaticProperty = (node) => !!node && (node.type === "ObjectProperty" || node.type === "ObjectMethod") && !node.computed;
|
210
|
+
const nonIdentifierRE = /^$|^\d|[^$\w\u00A0-\uFFFF]/;
|
211
|
+
const isSimpleIdentifier = (name) => !nonIdentifierRE.test(name);
|
212
|
+
function getTextLikeValue(node, excludeNumber) {
|
213
|
+
node = node.type === "JSXExpressionContainer" ? node.expression : node;
|
214
|
+
if (node.type === "StringLiteral") return node.value;
|
215
|
+
else if (!excludeNumber && (node.type === "NumericLiteral" || node.type === "BigIntLiteral")) return String(node.value);
|
216
|
+
else if (node.type === "TemplateLiteral" && node.expressions.length === 0) return node.quasis[0].value.cooked;
|
217
|
+
}
|
218
|
+
|
219
|
+
//#endregion
|
220
|
+
//#region src/utils/text.ts
|
126
221
|
const EMPTY_TEXT_REGEX = /^[\t\v\f \u00A0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF]*[\n\r]\s*$/;
|
127
222
|
const START_EMPTY_TEXT_REGEX = /^\s*[\n\r]/;
|
128
223
|
const END_EMPTY_TEXT_REGEX = /[\n\r]\s*$/;
|
@@ -136,59 +231,61 @@ function resolveJSXText(node) {
|
|
136
231
|
function isEmptyText(node) {
|
137
232
|
return node.type === "JSXText" && EMPTY_TEXT_REGEX.test(String(node.extra?.raw)) || node.type === "JSXExpressionContainer" && node.expression.type === "JSXEmptyExpression";
|
138
233
|
}
|
139
|
-
function
|
140
|
-
|
141
|
-
|
142
|
-
|
234
|
+
function getText(node, content) {
|
235
|
+
return content.ir.source.slice(node.start, node.end);
|
236
|
+
}
|
237
|
+
|
238
|
+
//#endregion
|
239
|
+
//#region src/utils/expression.ts
|
240
|
+
const locStub = {
|
241
|
+
start: {
|
242
|
+
line: 1,
|
243
|
+
column: 0,
|
244
|
+
index: 0
|
245
|
+
},
|
246
|
+
end: {
|
247
|
+
line: 1,
|
248
|
+
column: 0,
|
249
|
+
index: 0
|
250
|
+
},
|
251
|
+
filename: "",
|
252
|
+
identifierName: void 0
|
253
|
+
};
|
254
|
+
function createSimpleExpression(content, isStatic = false, ast) {
|
255
|
+
return {
|
256
|
+
loc: ast ? ast.loc : locStub,
|
257
|
+
content,
|
258
|
+
isStatic,
|
259
|
+
ast
|
260
|
+
};
|
261
|
+
}
|
262
|
+
const isLiteralWhitelisted = /* @__PURE__ */ makeMap("true,false,null,this");
|
263
|
+
function isConstantExpression(exp) {
|
264
|
+
return isLiteralWhitelisted(exp.content) || isGloballyAllowed(exp.content) || getLiteralExpressionValue(exp) !== null;
|
265
|
+
}
|
266
|
+
function getLiteralExpressionValue(exp) {
|
267
|
+
if (exp.ast) {
|
268
|
+
const res = getTextLikeValue(exp.ast);
|
269
|
+
if (res != null) return res;
|
143
270
|
}
|
144
|
-
return exp;
|
271
|
+
return exp.isStatic ? exp.content : null;
|
145
272
|
}
|
146
|
-
|
147
|
-
|
273
|
+
const EMPTY_EXPRESSION = createSimpleExpression("", true);
|
274
|
+
function resolveExpression(node, context) {
|
275
|
+
if (!node) return EMPTY_EXPRESSION;
|
148
276
|
node = unwrapTSNode(node.type === "JSXExpressionContainer" ? node.expression : node);
|
149
277
|
const isStatic = node.type === "StringLiteral" || node.type === "JSXText" || node.type === "JSXIdentifier";
|
150
|
-
|
151
|
-
|
152
|
-
if (source && !isStatic && effect && !isConstant(node)) {
|
153
|
-
source = `() => (${source})`;
|
154
|
-
node._offset = 7;
|
155
|
-
}
|
156
|
-
return resolveSimpleExpression(source, isStatic, location, isStatic ? void 0 : node);
|
157
|
-
}
|
158
|
-
function resolveSimpleExpression(source, isStatic, location, ast) {
|
159
|
-
const result = createSimpleExpression(source, isStatic, resolveLocation(location, source));
|
160
|
-
result.ast = ast ?? null;
|
161
|
-
return result;
|
162
|
-
}
|
163
|
-
function resolveLocation(location, context) {
|
164
|
-
return location ? {
|
165
|
-
start: {
|
166
|
-
line: location.start.line,
|
167
|
-
column: location.start.column + 1,
|
168
|
-
offset: location.start.index
|
169
|
-
},
|
170
|
-
end: {
|
171
|
-
line: location.end.line,
|
172
|
-
column: location.end.column + 1,
|
173
|
-
offset: location.end.index
|
174
|
-
},
|
175
|
-
source: isString(context) ? context : context.ir.source.slice(location.start.index, location.end.index)
|
176
|
-
} : {
|
177
|
-
start: {
|
178
|
-
line: 1,
|
179
|
-
column: 1,
|
180
|
-
offset: 0
|
181
|
-
},
|
182
|
-
end: {
|
183
|
-
line: 1,
|
184
|
-
column: 1,
|
185
|
-
offset: 0
|
186
|
-
},
|
187
|
-
source: ""
|
188
|
-
};
|
278
|
+
const source = node.type === "JSXEmptyExpression" ? "" : node.type === "JSXIdentifier" ? node.name : node.type === "StringLiteral" ? node.value : node.type === "JSXText" ? resolveJSXText(node) : node.type === "Identifier" ? node.name : context.ir.source.slice(node.start, node.end);
|
279
|
+
return createSimpleExpression(source, isStatic, node);
|
189
280
|
}
|
281
|
+
function propToExpression(prop, context) {
|
282
|
+
return prop.type === "JSXAttribute" && prop.value?.type === "JSXExpressionContainer" ? resolveExpression(prop.value.expression, context) : EMPTY_EXPRESSION;
|
283
|
+
}
|
284
|
+
|
285
|
+
//#endregion
|
286
|
+
//#region src/utils/directive.ts
|
190
287
|
const namespaceRE = /^(?:\$([\w-]+)\$)?([\w-]+)?/;
|
191
|
-
function resolveDirective(node, context
|
288
|
+
function resolveDirective(node, context) {
|
192
289
|
const { value, name } = node;
|
193
290
|
let nameString = name.type === "JSXNamespacedName" ? name.namespace.name : name.type === "JSXIdentifier" ? name.name : "";
|
194
291
|
const isDirective = nameString.startsWith("v-");
|
@@ -208,48 +305,73 @@ function resolveDirective(node, context, withFn = false) {
|
|
208
305
|
} else if (modifierString) [argString, ...modifiers] = modifierString.split("_");
|
209
306
|
}
|
210
307
|
}
|
211
|
-
const arg = isDirective ? argString && name.type === "JSXNamespacedName" ?
|
212
|
-
const exp = value ?
|
308
|
+
const arg = isDirective ? argString && name.type === "JSXNamespacedName" ? createSimpleExpression(argString, isStatic, name.name) : void 0 : createSimpleExpression(nameString, true, name);
|
309
|
+
const exp = value ? resolveExpression(value, context) : void 0;
|
213
310
|
return {
|
214
|
-
type: NodeTypes.DIRECTIVE,
|
215
311
|
name: isDirective ? nameString.slice(2) : "bind",
|
216
312
|
rawName: getText(name, context),
|
217
313
|
exp,
|
218
314
|
arg,
|
219
|
-
loc:
|
315
|
+
loc: node.loc,
|
220
316
|
modifiers: modifiers.map((modifier) => createSimpleExpression(modifier))
|
221
317
|
};
|
222
318
|
}
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
const name = openingElement.name.name;
|
232
|
-
return !isHTMLTag(name) && !isSVGTag(name);
|
233
|
-
} else return openingElement.name.type === "JSXMemberExpression";
|
319
|
+
|
320
|
+
//#endregion
|
321
|
+
//#region src/utils/transform.ts
|
322
|
+
function newDynamic() {
|
323
|
+
return {
|
324
|
+
flags: DynamicFlag.REFERENCED,
|
325
|
+
children: []
|
326
|
+
};
|
234
327
|
}
|
235
|
-
function
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
328
|
+
function newBlock(node) {
|
329
|
+
return {
|
330
|
+
type: 1,
|
331
|
+
node,
|
332
|
+
dynamic: newDynamic(),
|
333
|
+
effect: [],
|
334
|
+
operation: [],
|
335
|
+
returns: [],
|
336
|
+
tempId: 0
|
337
|
+
};
|
240
338
|
}
|
241
|
-
function
|
242
|
-
|
339
|
+
function createBranch(node, context, isVFor) {
|
340
|
+
context.node = node = wrapFragment(node);
|
341
|
+
const branch = newBlock(node);
|
342
|
+
const exitBlock = context.enterBlock(branch, isVFor);
|
343
|
+
context.reference();
|
344
|
+
return [branch, exitBlock];
|
243
345
|
}
|
244
|
-
function
|
245
|
-
if (node.type === "
|
346
|
+
function wrapFragment(node) {
|
347
|
+
if (node.type === "JSXFragment" || isTemplate(node)) return node;
|
348
|
+
return {
|
349
|
+
type: "JSXFragment",
|
350
|
+
openingFragment: { type: "JSXOpeningFragment" },
|
351
|
+
closingFragment: { type: "JSXClosingFragment" },
|
352
|
+
children: [node.type === "JSXElement" ? node : {
|
353
|
+
type: "JSXExpressionContainer",
|
354
|
+
expression: node
|
355
|
+
}]
|
356
|
+
};
|
246
357
|
}
|
247
358
|
|
248
359
|
//#endregion
|
249
|
-
//#region src/
|
360
|
+
//#region src/utils/generate.ts
|
250
361
|
const NEWLINE = Symbol(`newline`);
|
251
362
|
const INDENT_START = Symbol(`indent start`);
|
252
363
|
const INDENT_END = Symbol(`indent end`);
|
364
|
+
let NewlineType = /* @__PURE__ */ function(NewlineType$1) {
|
365
|
+
/** Start with `\n` */
|
366
|
+
NewlineType$1[NewlineType$1["Start"] = 0] = "Start";
|
367
|
+
/** Ends with `\n` */
|
368
|
+
NewlineType$1[NewlineType$1["End"] = -1] = "End";
|
369
|
+
/** No `\n` included */
|
370
|
+
NewlineType$1[NewlineType$1["None"] = -2] = "None";
|
371
|
+
/** Don't know, calc it */
|
372
|
+
NewlineType$1[NewlineType$1["Unknown"] = -3] = "Unknown";
|
373
|
+
return NewlineType$1;
|
374
|
+
}({});
|
253
375
|
function buildCodeFragment(...frag) {
|
254
376
|
const push = frag.push.bind(frag);
|
255
377
|
const unshift = frag.unshift.bind(frag);
|
@@ -335,8 +457,8 @@ function codeFragmentToString(code, context) {
|
|
335
457
|
let codegen = "";
|
336
458
|
const pos = {
|
337
459
|
line: 1,
|
338
|
-
column:
|
339
|
-
|
460
|
+
column: 0,
|
461
|
+
index: 0
|
340
462
|
};
|
341
463
|
let indentLevel = 0;
|
342
464
|
for (let frag of code) {
|
@@ -356,7 +478,7 @@ function codeFragmentToString(code, context) {
|
|
356
478
|
if (loc) addMapping(loc.start, name);
|
357
479
|
if (newlineIndex === NewlineType.Unknown) advancePositionWithMutation(pos, code$1);
|
358
480
|
else {
|
359
|
-
pos.
|
481
|
+
pos.index += code$1.length;
|
360
482
|
if (newlineIndex === NewlineType.None) pos.column += code$1.length;
|
361
483
|
else {
|
362
484
|
if (newlineIndex === NewlineType.End) newlineIndex = code$1.length - 1;
|
@@ -373,7 +495,7 @@ function codeFragmentToString(code, context) {
|
|
373
495
|
if (name !== null && !_names.has(name)) _names.add(name);
|
374
496
|
_mappings.add({
|
375
497
|
originalLine: loc.line,
|
376
|
-
originalColumn: loc.column
|
498
|
+
originalColumn: loc.column,
|
377
499
|
generatedLine: pos.line,
|
378
500
|
generatedColumn: pos.column - 1,
|
379
501
|
source: filename,
|
@@ -381,26 +503,238 @@ function codeFragmentToString(code, context) {
|
|
381
503
|
});
|
382
504
|
}
|
383
505
|
}
|
506
|
+
function advancePositionWithMutation(pos, source, numberOfCharacters = source.length) {
|
507
|
+
let linesCount = 0;
|
508
|
+
let lastNewLinePos = -1;
|
509
|
+
for (let i = 0; i < numberOfCharacters; i++) if (source.charCodeAt(i) === 10) {
|
510
|
+
linesCount++;
|
511
|
+
lastNewLinePos = i;
|
512
|
+
}
|
513
|
+
pos.index += numberOfCharacters;
|
514
|
+
pos.line += linesCount;
|
515
|
+
pos.column = lastNewLinePos === -1 ? pos.column + numberOfCharacters : numberOfCharacters - lastNewLinePos;
|
516
|
+
return pos;
|
517
|
+
}
|
518
|
+
function advancePositionWithClone(pos, source, numberOfCharacters = source.length) {
|
519
|
+
return advancePositionWithMutation({
|
520
|
+
index: pos.index,
|
521
|
+
line: pos.line,
|
522
|
+
column: pos.column
|
523
|
+
}, source, numberOfCharacters);
|
524
|
+
}
|
525
|
+
|
526
|
+
//#endregion
|
527
|
+
//#region src/utils/dom.ts
|
528
|
+
/**
|
529
|
+
* Copied from https://github.com/MananTank/validate-html-nesting
|
530
|
+
* with ISC license
|
531
|
+
*
|
532
|
+
* To avoid runtime dependency on validate-html-nesting
|
533
|
+
* This file should not change very often in the original repo
|
534
|
+
* but we may need to keep it up-to-date from time to time.
|
535
|
+
*/
|
536
|
+
/**
|
537
|
+
* returns true if given parent-child nesting is valid HTML
|
538
|
+
*/
|
539
|
+
function isValidHTMLNesting(parent, child) {
|
540
|
+
if (parent === "template") return true;
|
541
|
+
if (parent in onlyValidChildren) return onlyValidChildren[parent].has(child);
|
542
|
+
if (child in onlyValidParents) return onlyValidParents[child].has(parent);
|
543
|
+
if (parent in knownInvalidChildren && knownInvalidChildren[parent].has(child)) return false;
|
544
|
+
if (child in knownInvalidParents && knownInvalidParents[child].has(parent)) return false;
|
545
|
+
return true;
|
546
|
+
}
|
547
|
+
const headings = new Set([
|
548
|
+
"h1",
|
549
|
+
"h2",
|
550
|
+
"h3",
|
551
|
+
"h4",
|
552
|
+
"h5",
|
553
|
+
"h6"
|
554
|
+
]);
|
555
|
+
const emptySet = new Set([]);
|
556
|
+
/**
|
557
|
+
* maps element to set of elements that can be it's children, no other */
|
558
|
+
const onlyValidChildren = {
|
559
|
+
head: new Set([
|
560
|
+
"base",
|
561
|
+
"basefront",
|
562
|
+
"bgsound",
|
563
|
+
"link",
|
564
|
+
"meta",
|
565
|
+
"title",
|
566
|
+
"noscript",
|
567
|
+
"noframes",
|
568
|
+
"style",
|
569
|
+
"script",
|
570
|
+
"template"
|
571
|
+
]),
|
572
|
+
optgroup: new Set(["option"]),
|
573
|
+
select: new Set([
|
574
|
+
"optgroup",
|
575
|
+
"option",
|
576
|
+
"hr"
|
577
|
+
]),
|
578
|
+
table: new Set([
|
579
|
+
"caption",
|
580
|
+
"colgroup",
|
581
|
+
"tbody",
|
582
|
+
"tfoot",
|
583
|
+
"thead"
|
584
|
+
]),
|
585
|
+
tr: new Set(["td", "th"]),
|
586
|
+
colgroup: new Set(["col"]),
|
587
|
+
tbody: new Set(["tr"]),
|
588
|
+
thead: new Set(["tr"]),
|
589
|
+
tfoot: new Set(["tr"]),
|
590
|
+
script: emptySet,
|
591
|
+
iframe: emptySet,
|
592
|
+
option: emptySet,
|
593
|
+
textarea: emptySet,
|
594
|
+
style: emptySet,
|
595
|
+
title: emptySet
|
596
|
+
};
|
597
|
+
/** maps elements to set of elements which can be it's parent, no other */
|
598
|
+
const onlyValidParents = {
|
599
|
+
html: emptySet,
|
600
|
+
body: new Set(["html"]),
|
601
|
+
head: new Set(["html"]),
|
602
|
+
td: new Set(["tr"]),
|
603
|
+
colgroup: new Set(["table"]),
|
604
|
+
caption: new Set(["table"]),
|
605
|
+
tbody: new Set(["table"]),
|
606
|
+
tfoot: new Set(["table"]),
|
607
|
+
col: new Set(["colgroup"]),
|
608
|
+
th: new Set(["tr"]),
|
609
|
+
thead: new Set(["table"]),
|
610
|
+
tr: new Set([
|
611
|
+
"tbody",
|
612
|
+
"thead",
|
613
|
+
"tfoot"
|
614
|
+
]),
|
615
|
+
dd: new Set(["dl", "div"]),
|
616
|
+
dt: new Set(["dl", "div"]),
|
617
|
+
figcaption: new Set(["figure"]),
|
618
|
+
summary: new Set(["details"]),
|
619
|
+
area: new Set(["map"])
|
620
|
+
};
|
621
|
+
/** maps element to set of elements that can not be it's children, others can */
|
622
|
+
const knownInvalidChildren = {
|
623
|
+
p: new Set([
|
624
|
+
"address",
|
625
|
+
"article",
|
626
|
+
"aside",
|
627
|
+
"blockquote",
|
628
|
+
"center",
|
629
|
+
"details",
|
630
|
+
"dialog",
|
631
|
+
"dir",
|
632
|
+
"div",
|
633
|
+
"dl",
|
634
|
+
"fieldset",
|
635
|
+
"figure",
|
636
|
+
"footer",
|
637
|
+
"form",
|
638
|
+
"h1",
|
639
|
+
"h2",
|
640
|
+
"h3",
|
641
|
+
"h4",
|
642
|
+
"h5",
|
643
|
+
"h6",
|
644
|
+
"header",
|
645
|
+
"hgroup",
|
646
|
+
"hr",
|
647
|
+
"li",
|
648
|
+
"main",
|
649
|
+
"nav",
|
650
|
+
"menu",
|
651
|
+
"ol",
|
652
|
+
"p",
|
653
|
+
"pre",
|
654
|
+
"section",
|
655
|
+
"table",
|
656
|
+
"ul"
|
657
|
+
]),
|
658
|
+
svg: new Set([
|
659
|
+
"b",
|
660
|
+
"blockquote",
|
661
|
+
"br",
|
662
|
+
"code",
|
663
|
+
"dd",
|
664
|
+
"div",
|
665
|
+
"dl",
|
666
|
+
"dt",
|
667
|
+
"em",
|
668
|
+
"embed",
|
669
|
+
"h1",
|
670
|
+
"h2",
|
671
|
+
"h3",
|
672
|
+
"h4",
|
673
|
+
"h5",
|
674
|
+
"h6",
|
675
|
+
"hr",
|
676
|
+
"i",
|
677
|
+
"img",
|
678
|
+
"li",
|
679
|
+
"menu",
|
680
|
+
"meta",
|
681
|
+
"ol",
|
682
|
+
"p",
|
683
|
+
"pre",
|
684
|
+
"ruby",
|
685
|
+
"s",
|
686
|
+
"small",
|
687
|
+
"span",
|
688
|
+
"strong",
|
689
|
+
"sub",
|
690
|
+
"sup",
|
691
|
+
"table",
|
692
|
+
"u",
|
693
|
+
"ul",
|
694
|
+
"var"
|
695
|
+
])
|
696
|
+
};
|
697
|
+
/** maps element to set of elements that can not be it's parent, others can */
|
698
|
+
const knownInvalidParents = {
|
699
|
+
a: new Set(["a"]),
|
700
|
+
button: new Set(["button"]),
|
701
|
+
dd: new Set(["dd", "dt"]),
|
702
|
+
dt: new Set(["dd", "dt"]),
|
703
|
+
form: new Set(["form"]),
|
704
|
+
li: new Set(["li"]),
|
705
|
+
h1: headings,
|
706
|
+
h2: headings,
|
707
|
+
h3: headings,
|
708
|
+
h4: headings,
|
709
|
+
h5: headings,
|
710
|
+
h6: headings
|
711
|
+
};
|
712
|
+
function toValidAssetId(name, type) {
|
713
|
+
return `_${type}_${name.replaceAll(/\W/g, (searchValue, replaceValue) => {
|
714
|
+
return searchValue === "-" ? "_" : name.charCodeAt(replaceValue).toString();
|
715
|
+
})}`;
|
716
|
+
}
|
384
717
|
|
385
718
|
//#endregion
|
386
719
|
//#region src/generators/expression.ts
|
387
|
-
function genExpression(node, context, assignment) {
|
388
|
-
|
720
|
+
function genExpression(node, context, assignment, needWrap = false) {
|
721
|
+
let { content, ast, isStatic, loc } = node;
|
722
|
+
if (needWrap) content = `() => (${content})`;
|
389
723
|
if (isStatic) return [[
|
390
724
|
JSON.stringify(content),
|
391
725
|
NewlineType.None,
|
392
726
|
loc
|
393
727
|
]];
|
394
|
-
if (!node.content.trim() ||
|
728
|
+
if (!node.content.trim() || isConstantExpression(node)) return [[
|
395
729
|
content,
|
396
730
|
NewlineType.None,
|
397
731
|
loc
|
398
732
|
], assignment && ` = ${assignment}`];
|
399
|
-
if (ast
|
733
|
+
if (!ast) return genIdentifier(content, context, loc, assignment);
|
400
734
|
const ids = [];
|
401
735
|
const parentStackMap = /* @__PURE__ */ new Map();
|
402
736
|
const parentStack = [];
|
403
|
-
walkIdentifiers
|
737
|
+
walkIdentifiers(ast, (id) => {
|
404
738
|
ids.push(id);
|
405
739
|
parentStackMap.set(id, parentStack.slice());
|
406
740
|
}, false, parentStack);
|
@@ -408,7 +742,7 @@ function genExpression(node, context, assignment) {
|
|
408
742
|
if (ids.length) {
|
409
743
|
const [frag, push] = buildCodeFragment();
|
410
744
|
const isTSNode = ast && TS_NODE_TYPES.includes(ast.type);
|
411
|
-
const offset = (ast?.start ? ast.start - 1 : 0) - (
|
745
|
+
const offset = (ast?.start ? ast.start - 1 : 0) - (needWrap ? 7 : 0);
|
412
746
|
ids.sort((a, b) => a.start - b.start).forEach((id, i) => {
|
413
747
|
const start = id.start - 1 - offset;
|
414
748
|
const end = id.end - 1 - offset;
|
@@ -424,7 +758,8 @@ function genExpression(node, context, assignment) {
|
|
424
758
|
push(...genIdentifier(source, context, {
|
425
759
|
start: advancePositionWithClone(node.loc.start, source, start),
|
426
760
|
end: advancePositionWithClone(node.loc.start, source, end),
|
427
|
-
|
761
|
+
filename: "",
|
762
|
+
identifierName: void 0
|
428
763
|
}, hasMemberExpression ? void 0 : assignment, parent));
|
429
764
|
if (i === ids.length - 1 && end < content.length && !isTSNode) push([content.slice(end), NewlineType.Unknown]);
|
430
765
|
});
|
@@ -487,7 +822,7 @@ function genVModel(oper, context) {
|
|
487
822
|
}
|
488
823
|
function genModelHandler(exp, context) {
|
489
824
|
return [
|
490
|
-
|
825
|
+
"_value => (",
|
491
826
|
...genExpression(exp, context, "_value"),
|
492
827
|
")"
|
493
828
|
];
|
@@ -528,7 +863,7 @@ function genCustomDirectives(opers, context) {
|
|
528
863
|
const directives = genMulti(DELIMITERS_ARRAY, ...directiveItems);
|
529
864
|
return [NEWLINE, ...genCall(helper("withVaporDirectives"), element, directives)];
|
530
865
|
function genDirectiveItem({ dir, name, asset }) {
|
531
|
-
const directiveVar = asset ? toValidAssetId(name, "directive") : genExpression(
|
866
|
+
const directiveVar = asset ? toValidAssetId(name, "directive") : genExpression(createSimpleExpression(name), context);
|
532
867
|
const value = dir.exp && ["() => ", ...genExpression(dir.exp, context)];
|
533
868
|
const argument = dir.arg && genExpression(dir.arg, context);
|
534
869
|
const modifiers = !!dir.modifiers.length && [
|
@@ -598,22 +933,20 @@ function genEventHandler(context, value, modifiers = {
|
|
598
933
|
keys: []
|
599
934
|
}, extraWrap = false) {
|
600
935
|
let handlerExp = [`() => {}`];
|
601
|
-
if (value && value.content.trim()) if (isMemberExpression(value
|
936
|
+
if (value && value.content.trim()) if (isMemberExpression(value)) {
|
602
937
|
handlerExp = genExpression(value, context);
|
603
938
|
if (!extraWrap) handlerExp = [
|
604
939
|
`e => `,
|
605
940
|
...handlerExp,
|
606
941
|
`(e)`
|
607
942
|
];
|
608
|
-
} else if (isFnExpression(value
|
943
|
+
} else if (isFnExpression(value)) handlerExp = genExpression(value, context);
|
609
944
|
else {
|
610
|
-
const referencesEvent = value.content.includes("$event");
|
611
945
|
const hasMultipleStatements = value.content.includes(`;`);
|
612
|
-
const expr = referencesEvent ? context.withId(() => genExpression(value, context), { $event: null }) : genExpression(value, context);
|
613
946
|
handlerExp = [
|
614
|
-
|
947
|
+
"() => ",
|
615
948
|
hasMultipleStatements ? "{" : "(",
|
616
|
-
...
|
949
|
+
...genExpression(value, context),
|
617
950
|
hasMultipleStatements ? "}" : ")"
|
618
951
|
];
|
619
952
|
}
|
@@ -738,7 +1071,7 @@ function genCreateComponent(operation, context) {
|
|
738
1071
|
")"
|
739
1072
|
];
|
740
1073
|
else if (operation.asset) return toValidAssetId(operation.tag, "component");
|
741
|
-
else return genExpression(
|
1074
|
+
else return genExpression(createSimpleExpression(operation.tag), context);
|
742
1075
|
}
|
743
1076
|
}
|
744
1077
|
function genRawProps(props, context) {
|
@@ -907,8 +1240,8 @@ function genSlotBlockWithProps(oper, context) {
|
|
907
1240
|
if (isDestructureAssignment = !!props.ast) {
|
908
1241
|
[depth, exitScope] = context.enterScope();
|
909
1242
|
propsName = `_slotProps${depth}`;
|
910
|
-
walkIdentifiers
|
911
|
-
if (isLocal) idsOfProps.add(id.name);
|
1243
|
+
walkIdentifiers(props.ast, (id, _, __, isReference, isLocal) => {
|
1244
|
+
if (isReference && !isLocal) idsOfProps.add(id.name);
|
912
1245
|
}, true);
|
913
1246
|
} else idsOfProps.add(propsName = rawProps);
|
914
1247
|
}
|
@@ -978,8 +1311,7 @@ function genFor(oper, context) {
|
|
978
1311
|
}
|
979
1312
|
if (pathInfo.dynamic) {
|
980
1313
|
const node = idMap[id$1] = createSimpleExpression(path);
|
981
|
-
|
982
|
-
node.ast = parseExpression(`(${path})`, { plugins: plugins ? [...plugins, "typescript"] : ["typescript"] });
|
1314
|
+
node.ast = parseExpression(`(${path})`, { plugins: context.options.expressionPlugins });
|
983
1315
|
} else idMap[id$1] = path;
|
984
1316
|
} else idMap[id$1] = path;
|
985
1317
|
});
|
@@ -996,7 +1328,7 @@ function genFor(oper, context) {
|
|
996
1328
|
idMap[rawIndex] = `${indexVar}.value`;
|
997
1329
|
idMap[indexVar] = null;
|
998
1330
|
}
|
999
|
-
const { selectorPatterns, keyOnlyBindingPatterns } = matchPatterns(render, keyProp, idMap);
|
1331
|
+
const { selectorPatterns, keyOnlyBindingPatterns } = matchPatterns(render, keyProp, idMap, context.ir.source);
|
1000
1332
|
const selectorDeclarations = [];
|
1001
1333
|
const selectorSetup = [];
|
1002
1334
|
for (const [i, { selector }] of selectorPatterns.entries()) {
|
@@ -1038,8 +1370,8 @@ function genFor(oper, context) {
|
|
1038
1370
|
const map = /* @__PURE__ */ new Map();
|
1039
1371
|
if (value) {
|
1040
1372
|
rawValue = value && value.content;
|
1041
|
-
if (value.ast) walkIdentifiers(value.ast, (id$1, _, parentStack,
|
1042
|
-
if (isLocal) {
|
1373
|
+
if (value.ast && value.ast.type !== "Identifier") walkIdentifiers(value.ast, (id$1, _, parentStack, isReference, isLocal) => {
|
1374
|
+
if (isReference && !isLocal) {
|
1043
1375
|
let path = "";
|
1044
1376
|
let isDynamic = false;
|
1045
1377
|
let helper$1;
|
@@ -1052,11 +1384,11 @@ function genFor(oper, context) {
|
|
1052
1384
|
isDynamic = true;
|
1053
1385
|
path += `[${value.content.slice(parent.key.start - 1, parent.key.end - 1)}]`;
|
1054
1386
|
} else path += `.${parent.key.name}`;
|
1055
|
-
else if (parent.type === "
|
1387
|
+
else if (parent.type === "ArrayExpression") {
|
1056
1388
|
const index$1 = parent.elements.indexOf(child);
|
1057
|
-
if (child.type === "
|
1389
|
+
if (child.type === "SpreadElement") path += `.slice(${index$1})`;
|
1058
1390
|
else path += `[${index$1}]`;
|
1059
|
-
} else if (parent.type === "
|
1391
|
+
} else if (parent.type === "ObjectExpression" && child.type === "SpreadElement") {
|
1060
1392
|
helper$1 = context.helper("getRestElement");
|
1061
1393
|
helperArgs = `[${parent.properties.filter((p) => p.type === "ObjectProperty").map((p) => {
|
1062
1394
|
if (p.key.type === "StringLiteral") return JSON.stringify(p.key.value);
|
@@ -1066,11 +1398,6 @@ function genFor(oper, context) {
|
|
1066
1398
|
} else return JSON.stringify(p.key.name);
|
1067
1399
|
}).join(", ")}]`;
|
1068
1400
|
}
|
1069
|
-
if (child.type === "AssignmentPattern" && (parent.type === "ObjectProperty" || parent.type === "ArrayPattern")) {
|
1070
|
-
isDynamic = true;
|
1071
|
-
helper$1 = context.helper("getDefaultValue");
|
1072
|
-
helperArgs = value.content.slice(child.right.start - 1, child.right.end - 1);
|
1073
|
-
}
|
1074
1401
|
}
|
1075
1402
|
map.set(id$1.name, {
|
1076
1403
|
path,
|
@@ -1106,17 +1433,17 @@ function genFor(oper, context) {
|
|
1106
1433
|
return idMap$1;
|
1107
1434
|
}
|
1108
1435
|
}
|
1109
|
-
function matchPatterns(render, keyProp, idMap) {
|
1436
|
+
function matchPatterns(render, keyProp, idMap, source) {
|
1110
1437
|
const selectorPatterns = [];
|
1111
1438
|
const keyOnlyBindingPatterns = [];
|
1112
1439
|
render.effect = render.effect.filter((effect) => {
|
1113
1440
|
if (keyProp !== void 0) {
|
1114
|
-
const selector = matchSelectorPattern(effect, keyProp.
|
1441
|
+
const selector = matchSelectorPattern(effect, keyProp.content, idMap, source);
|
1115
1442
|
if (selector) {
|
1116
1443
|
selectorPatterns.push(selector);
|
1117
1444
|
return false;
|
1118
1445
|
}
|
1119
|
-
const keyOnly = matchKeyOnlyBindingPattern(effect, keyProp.
|
1446
|
+
const keyOnly = matchKeyOnlyBindingPattern(effect, keyProp.content, source);
|
1120
1447
|
if (keyOnly) {
|
1121
1448
|
keyOnlyBindingPatterns.push(keyOnly);
|
1122
1449
|
return false;
|
@@ -1129,37 +1456,37 @@ function matchPatterns(render, keyProp, idMap) {
|
|
1129
1456
|
selectorPatterns
|
1130
1457
|
};
|
1131
1458
|
}
|
1132
|
-
function matchKeyOnlyBindingPattern(effect,
|
1459
|
+
function matchKeyOnlyBindingPattern(effect, key, source) {
|
1133
1460
|
if (effect.expressions.length === 1) {
|
1134
1461
|
const ast = effect.expressions[0].ast;
|
1135
|
-
if (typeof ast === "object" && ast !== null && isKeyOnlyBinding(ast,
|
1462
|
+
if (typeof ast === "object" && ast !== null && isKeyOnlyBinding(ast, key, source)) return { effect };
|
1136
1463
|
}
|
1137
1464
|
}
|
1138
|
-
function matchSelectorPattern(effect,
|
1465
|
+
function matchSelectorPattern(effect, key, idMap, source) {
|
1139
1466
|
if (effect.expressions.length === 1) {
|
1140
1467
|
const ast = effect.expressions[0].ast;
|
1141
|
-
const offset = effect.expressions[0].loc.start.
|
1468
|
+
const offset = effect.expressions[0].loc.start.index;
|
1142
1469
|
if (typeof ast === "object" && ast) {
|
1143
1470
|
const matcheds = [];
|
1144
1471
|
walkAST(ast, { enter(node) {
|
1145
1472
|
if (typeof node === "object" && node && node.type === "BinaryExpression" && node.operator === "===" && node.left.type !== "PrivateName") {
|
1146
1473
|
const { left, right } = node;
|
1147
1474
|
for (const [a, b] of [[left, right], [right, left]]) {
|
1148
|
-
const aIsKey = isKeyOnlyBinding(a,
|
1149
|
-
const bIsKey = isKeyOnlyBinding(b,
|
1475
|
+
const aIsKey = isKeyOnlyBinding(a, key, source);
|
1476
|
+
const bIsKey = isKeyOnlyBinding(b, key, source);
|
1150
1477
|
const bVars = analyzeVariableScopes(b, idMap);
|
1151
1478
|
if (aIsKey && !bIsKey && !bVars.locals.length) matcheds.push([a, b]);
|
1152
1479
|
}
|
1153
1480
|
}
|
1154
1481
|
} });
|
1155
1482
|
if (matcheds.length === 1) {
|
1156
|
-
const [key, selector] = matcheds[0];
|
1483
|
+
const [key$1, selector] = matcheds[0];
|
1157
1484
|
const content$1 = effect.expressions[0].content;
|
1158
1485
|
let hasExtraId = false;
|
1159
1486
|
const parentStackMap = /* @__PURE__ */ new Map();
|
1160
1487
|
const parentStack = [];
|
1161
1488
|
walkIdentifiers(ast, (id) => {
|
1162
|
-
if (id.start !== key.start && id.start !== selector.start) hasExtraId = true;
|
1489
|
+
if (id.start !== key$1.start && id.start !== selector.start) hasExtraId = true;
|
1163
1490
|
parentStackMap.set(id, parentStack.slice());
|
1164
1491
|
}, false, parentStack);
|
1165
1492
|
if (!hasExtraId) {
|
@@ -1180,12 +1507,12 @@ function matchSelectorPattern(effect, keyAst, idMap) {
|
|
1180
1507
|
}
|
1181
1508
|
}
|
1182
1509
|
const content = effect.expressions[0].content;
|
1183
|
-
if (typeof ast === "object" && ast && ast.type === "ConditionalExpression" && ast.test.type === "BinaryExpression" && ast.test.operator === "===" && ast.test.left.type !== "PrivateName" &&
|
1510
|
+
if (typeof ast === "object" && ast && ast.type === "ConditionalExpression" && ast.test.type === "BinaryExpression" && ast.test.operator === "===" && ast.test.left.type !== "PrivateName" && isConstantNode(ast.consequent) && isConstantNode(ast.alternate)) {
|
1184
1511
|
const left = ast.test.left;
|
1185
1512
|
const right = ast.test.right;
|
1186
1513
|
for (const [a, b] of [[left, right], [right, left]]) {
|
1187
|
-
const aIsKey = isKeyOnlyBinding(a,
|
1188
|
-
const bIsKey = isKeyOnlyBinding(b,
|
1514
|
+
const aIsKey = isKeyOnlyBinding(a, key, source);
|
1515
|
+
const bIsKey = isKeyOnlyBinding(b, key, source);
|
1189
1516
|
const bVars = analyzeVariableScopes(b, idMap);
|
1190
1517
|
if (aIsKey && !bIsKey && !bVars.locals.length) return {
|
1191
1518
|
effect,
|
@@ -1220,10 +1547,10 @@ function analyzeVariableScopes(ast, idMap) {
|
|
1220
1547
|
locals
|
1221
1548
|
};
|
1222
1549
|
}
|
1223
|
-
function isKeyOnlyBinding(expr,
|
1550
|
+
function isKeyOnlyBinding(expr, key, source) {
|
1224
1551
|
let only = true;
|
1225
1552
|
walkAST(expr, { enter(node) {
|
1226
|
-
if (
|
1553
|
+
if (source.slice(node.start, node.end) === key) {
|
1227
1554
|
this.skip();
|
1228
1555
|
return;
|
1229
1556
|
}
|
@@ -1279,7 +1606,7 @@ function genDeclareOldRef(oper) {
|
|
1279
1606
|
function genSetText(oper, context) {
|
1280
1607
|
const { helper } = context;
|
1281
1608
|
const { element, values, generated } = oper;
|
1282
|
-
const texts = combineValues(values, context, true);
|
1609
|
+
const texts = combineValues(values, context, true, true);
|
1283
1610
|
return [NEWLINE, ...genCall(helper("setText"), `${generated ? "x" : "n"}${element}`, texts)];
|
1284
1611
|
}
|
1285
1612
|
function genGetTextChild(oper, context) {
|
@@ -1287,21 +1614,22 @@ function genGetTextChild(oper, context) {
|
|
1287
1614
|
}
|
1288
1615
|
function genSetNodes(oper, context) {
|
1289
1616
|
const { helper } = context;
|
1290
|
-
const { element, values, generated } = oper;
|
1291
|
-
return [NEWLINE, ...genCall(helper("setNodes"), `${generated ? "x" : "n"}${element}`, combineValues(values, context))];
|
1617
|
+
const { element, values, generated, once } = oper;
|
1618
|
+
return [NEWLINE, ...genCall(helper("setNodes"), `${generated ? "x" : "n"}${element}`, combineValues(values, context, once))];
|
1292
1619
|
}
|
1293
1620
|
function genCreateNodes(oper, context) {
|
1294
1621
|
const { helper } = context;
|
1295
|
-
const { id, values } = oper;
|
1622
|
+
const { id, values, once } = oper;
|
1296
1623
|
return [
|
1297
1624
|
NEWLINE,
|
1298
1625
|
`const n${id} = `,
|
1299
|
-
...genCall(helper("createNodes"), values && combineValues(values, context))
|
1626
|
+
...genCall(helper("createNodes"), values && combineValues(values, context, once))
|
1300
1627
|
];
|
1301
1628
|
}
|
1302
|
-
function combineValues(values, context, setText) {
|
1629
|
+
function combineValues(values, context, once, setText) {
|
1303
1630
|
return values.flatMap((value, i) => {
|
1304
|
-
|
1631
|
+
const { content, isStatic, ast } = value;
|
1632
|
+
let exp = genExpression(value, context, void 0, !once && !setText && !!content && !isStatic && !!ast && !isConstantNode(ast));
|
1305
1633
|
if (setText && getLiteralExpressionValue(value) == null) exp = genCall(context.helper("toDisplayString"), exp);
|
1306
1634
|
if (i > 0) exp.unshift(setText ? " + " : ", ");
|
1307
1635
|
return exp;
|
@@ -1508,18 +1836,10 @@ var CodegenContext = class {
|
|
1508
1836
|
constructor(ir, options) {
|
1509
1837
|
this.ir = ir;
|
1510
1838
|
const defaultOptions$1 = {
|
1511
|
-
mode: "module",
|
1512
1839
|
sourceMap: false,
|
1513
|
-
filename: `
|
1514
|
-
|
1515
|
-
|
1516
|
-
runtimeModuleName: `vue`,
|
1517
|
-
ssrRuntimeModuleName: "vue/server-renderer",
|
1518
|
-
ssr: false,
|
1519
|
-
isTS: false,
|
1520
|
-
inSSR: false,
|
1521
|
-
templates: [],
|
1522
|
-
expressionPlugins: []
|
1840
|
+
filename: `index.jsx`,
|
1841
|
+
expressionPlugins: ["jsx"],
|
1842
|
+
templates: []
|
1523
1843
|
};
|
1524
1844
|
this.options = extend(defaultOptions$1, options);
|
1525
1845
|
this.block = ir.block;
|
@@ -1550,26 +1870,18 @@ function generate(ir, options = {}) {
|
|
1550
1870
|
//#region src/transform.ts
|
1551
1871
|
const defaultOptions = {
|
1552
1872
|
source: "",
|
1553
|
-
|
1554
|
-
|
1555
|
-
hmr: false,
|
1556
|
-
cacheHandlers: false,
|
1873
|
+
sourceMap: false,
|
1874
|
+
filename: "index.jsx",
|
1557
1875
|
nodeTransforms: [],
|
1558
1876
|
directiveTransforms: {},
|
1559
1877
|
templates: [],
|
1560
|
-
transformHoist: null,
|
1561
|
-
isBuiltInComponent: NOOP,
|
1562
1878
|
isCustomElement: NOOP,
|
1563
1879
|
expressionPlugins: [],
|
1564
|
-
scopeId: null,
|
1565
|
-
slotted: true,
|
1566
|
-
ssr: false,
|
1567
|
-
inSSR: false,
|
1568
|
-
ssrCssVars: ``,
|
1569
1880
|
isTS: false,
|
1570
1881
|
withFallback: false,
|
1571
|
-
onError:
|
1572
|
-
|
1882
|
+
onError: (error) => {
|
1883
|
+
throw error;
|
1884
|
+
}
|
1573
1885
|
};
|
1574
1886
|
var TransformContext = class TransformContext {
|
1575
1887
|
parent = null;
|
@@ -1582,7 +1894,6 @@ var TransformContext = class TransformContext {
|
|
1582
1894
|
dynamic;
|
1583
1895
|
inVOnce = false;
|
1584
1896
|
inVFor = 0;
|
1585
|
-
comment = [];
|
1586
1897
|
component;
|
1587
1898
|
directive;
|
1588
1899
|
slots = [];
|
@@ -1635,7 +1946,7 @@ var TransformContext = class TransformContext {
|
|
1635
1946
|
registerEffect(expressions, operation, getEffectIndex = () => this.block.effect.length, getOperationIndex = () => this.block.operation.length) {
|
1636
1947
|
const operations = [operation].flat();
|
1637
1948
|
expressions = expressions.filter((exp) => !isConstantExpression(exp));
|
1638
|
-
if (this.inVOnce || expressions.length === 0 || expressions.every((e) => e.ast &&
|
1949
|
+
if (this.inVOnce || expressions.length === 0 || expressions.every((e) => e.ast && isConstantNode(e.ast))) return this.registerOperation(operations, getOperationIndex);
|
1639
1950
|
this.block.effect.splice(getEffectIndex(), 0, {
|
1640
1951
|
expressions,
|
1641
1952
|
operations
|
@@ -1807,10 +2118,8 @@ function transformComponentElement(tag, propsResult, singleRoot, context) {
|
|
1807
2118
|
context.slots = [];
|
1808
2119
|
}
|
1809
2120
|
function transformNativeElement(tag, propsResult, singleRoot, context, getEffectIndex, getOperationIndex) {
|
1810
|
-
const { scopeId } = context.options;
|
1811
2121
|
let template = "";
|
1812
2122
|
template += `<${tag}`;
|
1813
|
-
if (scopeId) template += ` ${scopeId}`;
|
1814
2123
|
const dynamicProps = [];
|
1815
2124
|
if (propsResult[0]) {
|
1816
2125
|
const [, dynamicArgs, expressions] = propsResult;
|
@@ -1868,7 +2177,7 @@ function buildProps(node, context, isComponent) {
|
|
1868
2177
|
});
|
1869
2178
|
continue;
|
1870
2179
|
}
|
1871
|
-
const result = transformProp(prop, node, context);
|
2180
|
+
const result = transformProp(prop, node, isComponent, context);
|
1872
2181
|
if (result) {
|
1873
2182
|
dynamicExpr.push(result.key, result.value);
|
1874
2183
|
if (isComponent && !result.key.isStatic) {
|
@@ -1888,15 +2197,16 @@ function buildProps(node, context, isComponent) {
|
|
1888
2197
|
const irProps = dedupeProperties(results);
|
1889
2198
|
return [false, irProps];
|
1890
2199
|
}
|
1891
|
-
function transformProp(prop, node, context) {
|
2200
|
+
function transformProp(prop, node, isComponent, context) {
|
1892
2201
|
if (prop.type === "JSXSpreadAttribute") return;
|
1893
2202
|
let name = prop.name.type === "JSXIdentifier" ? prop.name.name : prop.name.type === "JSXNamespacedName" ? prop.name.namespace.name : "";
|
1894
2203
|
name = name.split("_")[0];
|
1895
|
-
|
2204
|
+
let value;
|
2205
|
+
if (!isDirectiveRegex.test(name) && !isEventRegex.test(name) && (!prop.value || (value = getTextLikeValue(prop.value, isComponent)) != null)) {
|
1896
2206
|
if (isReservedProp(name)) return;
|
1897
2207
|
return {
|
1898
|
-
key:
|
1899
|
-
value: prop.value
|
2208
|
+
key: createSimpleExpression(name, true, prop.name),
|
2209
|
+
value: prop.value ? createSimpleExpression(value, true, prop.value) : createSimpleExpression("true")
|
1900
2210
|
};
|
1901
2211
|
}
|
1902
2212
|
name = isEventRegex.test(name) ? "on" : isDirectiveRegex.test(name) ? name.slice(2) : "bind";
|
@@ -1977,7 +2287,7 @@ function processConditionalExpression(node, context) {
|
|
1977
2287
|
id,
|
1978
2288
|
condition,
|
1979
2289
|
positive: branch,
|
1980
|
-
once: context.inVOnce ||
|
2290
|
+
once: context.inVOnce || isConstantNode(test)
|
1981
2291
|
};
|
1982
2292
|
return [() => {
|
1983
2293
|
onExit();
|
@@ -2043,7 +2353,7 @@ const transformText = (node, context) => {
|
|
2043
2353
|
else processInterpolation(context);
|
2044
2354
|
else if (node.type === "JSXText") {
|
2045
2355
|
const value = resolveJSXText(node);
|
2046
|
-
if (value) context.template += value;
|
2356
|
+
if (value) context.template += escapeHtml(value);
|
2047
2357
|
else context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
|
2048
2358
|
}
|
2049
2359
|
};
|
@@ -2064,6 +2374,7 @@ function processInterpolation(context) {
|
|
2064
2374
|
if (isFragmentNode(parent) || findProp(parent, "v-slot")) context.registerOperation({
|
2065
2375
|
type: IRNodeTypes.CREATE_NODES,
|
2066
2376
|
id,
|
2377
|
+
once: context.inVOnce,
|
2067
2378
|
values
|
2068
2379
|
});
|
2069
2380
|
else {
|
@@ -2071,6 +2382,7 @@ function processInterpolation(context) {
|
|
2071
2382
|
context.registerOperation({
|
2072
2383
|
type: IRNodeTypes.SET_NODES,
|
2073
2384
|
element: id,
|
2385
|
+
once: context.inVOnce,
|
2074
2386
|
values
|
2075
2387
|
});
|
2076
2388
|
}
|
@@ -2078,7 +2390,7 @@ function processInterpolation(context) {
|
|
2078
2390
|
function processTextContainer(children, context) {
|
2079
2391
|
const values = createTextLikeExpressions(children, context);
|
2080
2392
|
const literals = values.map(getLiteralExpressionValue);
|
2081
|
-
if (literals.every((l) => l != null)) context.childrenTemplate = literals
|
2393
|
+
if (literals.every((l) => l != null)) context.childrenTemplate = literals;
|
2082
2394
|
else {
|
2083
2395
|
context.childrenTemplate = [" "];
|
2084
2396
|
context.registerOperation({
|
@@ -2088,6 +2400,7 @@ function processTextContainer(children, context) {
|
|
2088
2400
|
context.registerOperation({
|
2089
2401
|
type: IRNodeTypes.SET_NODES,
|
2090
2402
|
element: context.reference(),
|
2403
|
+
once: context.inVOnce,
|
2091
2404
|
values,
|
2092
2405
|
generated: true
|
2093
2406
|
});
|
@@ -2098,7 +2411,7 @@ function createTextLikeExpressions(nodes, context) {
|
|
2098
2411
|
for (const node of nodes) {
|
2099
2412
|
markNonTemplate(node, context);
|
2100
2413
|
if (isEmptyText(node)) continue;
|
2101
|
-
values.push(resolveExpression(node, context
|
2414
|
+
values.push(resolveExpression(node, context));
|
2102
2415
|
}
|
2103
2416
|
return values;
|
2104
2417
|
}
|
@@ -2113,7 +2426,7 @@ const transformVBind = (dir, node, context) => {
|
|
2113
2426
|
if (!loc || name.type === "JSXNamespacedName") return;
|
2114
2427
|
const [nameString, ...modifiers] = name.name.split("_");
|
2115
2428
|
const exp = resolveExpression(value, context);
|
2116
|
-
let arg =
|
2429
|
+
let arg = createSimpleExpression(nameString, true, dir.name);
|
2117
2430
|
if (arg.isStatic && isReservedProp(arg.content)) return;
|
2118
2431
|
let camel = false;
|
2119
2432
|
if (modifiers.includes("camel")) if (arg.isStatic) arg = extend({}, arg, { content: camelize(arg.content) });
|
@@ -2133,12 +2446,12 @@ const transformVFor = createStructuralDirectiveTransform("for", processFor);
|
|
2133
2446
|
function processFor(node, dir, context) {
|
2134
2447
|
const { value, index, key, source } = getForParseResult(dir, context);
|
2135
2448
|
if (!source) {
|
2136
|
-
context.options.onError(createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,
|
2449
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc));
|
2137
2450
|
return;
|
2138
2451
|
}
|
2139
2452
|
const keyProp = findProp(node, "key");
|
2140
2453
|
const keyProperty = keyProp && propToExpression(keyProp, context);
|
2141
|
-
const isComponent = isJSXComponent(node);
|
2454
|
+
const isComponent = isJSXComponent(node) || isTemplateWithSingleComponent(node);
|
2142
2455
|
const id = context.reference();
|
2143
2456
|
context.dynamic.flags |= DynamicFlag.NON_TEMPLATE | DynamicFlag.INSERT;
|
2144
2457
|
const [render, exitBlock] = createBranch(node, context, true);
|
@@ -2155,7 +2468,7 @@ function processFor(node, dir, context) {
|
|
2155
2468
|
index,
|
2156
2469
|
keyProp: keyProperty,
|
2157
2470
|
render,
|
2158
|
-
once: context.inVOnce || !!(source.ast &&
|
2471
|
+
once: context.inVOnce || !!(source.ast && isConstantNode(source.ast)),
|
2159
2472
|
component: isComponent,
|
2160
2473
|
onlyChild: !!isOnlyChild
|
2161
2474
|
};
|
@@ -2167,13 +2480,13 @@ function getForParseResult(dir, context) {
|
|
2167
2480
|
if (dir.value.type === "JSXExpressionContainer" && dir.value.expression.type === "BinaryExpression") {
|
2168
2481
|
if (dir.value.expression.left.type === "SequenceExpression") {
|
2169
2482
|
const expressions = dir.value.expression.left.expressions;
|
2170
|
-
value = expressions[0] &&
|
2483
|
+
value = expressions[0] && resolveExpression(expressions[0], context);
|
2171
2484
|
key = expressions[1] && resolveExpression(expressions[1], context);
|
2172
2485
|
index = expressions[2] && resolveExpression(expressions[2], context);
|
2173
|
-
} else value =
|
2486
|
+
} else value = resolveExpression(dir.value.expression.left, context);
|
2174
2487
|
source = resolveExpression(dir.value.expression.right, context);
|
2175
2488
|
}
|
2176
|
-
} else context.options.onError(createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION,
|
2489
|
+
} else context.options.onError(createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc));
|
2177
2490
|
return {
|
2178
2491
|
value,
|
2179
2492
|
index,
|
@@ -2181,18 +2494,21 @@ function getForParseResult(dir, context) {
|
|
2181
2494
|
source
|
2182
2495
|
};
|
2183
2496
|
}
|
2497
|
+
function isTemplateWithSingleComponent(node) {
|
2498
|
+
const nonCommentChildren = node.children.filter((c) => !isEmptyText(c));
|
2499
|
+
return nonCommentChildren.length === 1 && isJSXComponent(nonCommentChildren[0]);
|
2500
|
+
}
|
2184
2501
|
|
2185
2502
|
//#endregion
|
2186
2503
|
//#region src/transforms/vHtml.ts
|
2187
2504
|
const transformVHtml = (dir, node, context) => {
|
2188
2505
|
let exp;
|
2189
|
-
const loc = resolveLocation(dir.loc, context);
|
2190
2506
|
if (!dir.value) {
|
2191
|
-
context.options.onError(
|
2507
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_HTML_NO_EXPRESSION, dir.loc));
|
2192
2508
|
exp = EMPTY_EXPRESSION;
|
2193
2509
|
} else exp = resolveExpression(dir.value, context);
|
2194
2510
|
if (node.children.length) {
|
2195
|
-
context.options.onError(
|
2511
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_HTML_WITH_CHILDREN, dir.loc));
|
2196
2512
|
context.childrenTemplate.length = 0;
|
2197
2513
|
}
|
2198
2514
|
context.registerEffect([exp], {
|
@@ -2213,9 +2529,8 @@ const transformedIfNode = /* @__PURE__ */ new WeakMap();
|
|
2213
2529
|
function processIf(node, attribute, context) {
|
2214
2530
|
const dir = resolveDirective(attribute, context);
|
2215
2531
|
if (dir.name !== "else" && (!dir.exp || !dir.exp.content.trim())) {
|
2216
|
-
const loc = dir.exp ? dir.exp.loc : resolveLocation(node.loc, context);
|
2217
2532
|
context.options.onError(createCompilerError(ErrorCodes.X_V_IF_NO_EXPRESSION, dir.loc));
|
2218
|
-
dir.exp = createSimpleExpression(`true`, false,
|
2533
|
+
dir.exp = createSimpleExpression(`true`, false, dir.exp ? dir.exp.ast : node);
|
2219
2534
|
}
|
2220
2535
|
context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
|
2221
2536
|
transformedIfNode.set(node, dir);
|
@@ -2230,7 +2545,7 @@ function processIf(node, attribute, context) {
|
|
2230
2545
|
id,
|
2231
2546
|
condition: dir.exp,
|
2232
2547
|
positive: branch,
|
2233
|
-
once: context.inVOnce ||
|
2548
|
+
once: context.inVOnce || isConstantNode(attribute.value)
|
2234
2549
|
};
|
2235
2550
|
};
|
2236
2551
|
} else {
|
@@ -2245,12 +2560,11 @@ function processIf(node, attribute, context) {
|
|
2245
2560
|
}
|
2246
2561
|
}
|
2247
2562
|
if (!siblingIf || !lastIfNode || lastIfNode.type !== IRNodeTypes.IF) {
|
2248
|
-
context.options.onError(createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
2563
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
|
2249
2564
|
return;
|
2250
2565
|
}
|
2251
2566
|
while (lastIfNode.negative && lastIfNode.negative.type === IRNodeTypes.IF) lastIfNode = lastIfNode.negative;
|
2252
|
-
if (dir.name === "else-if" && lastIfNode.negative) context.options.onError(createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
2253
|
-
context.root.comment = [];
|
2567
|
+
if (dir.name === "else-if" && lastIfNode.negative) context.options.onError(createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc));
|
2254
2568
|
const [branch, onExit] = createBranch(node, context);
|
2255
2569
|
if (dir.name === "else") lastIfNode.negative = branch;
|
2256
2570
|
else lastIfNode.negative = {
|
@@ -2286,7 +2600,7 @@ const transformVModel = (_dir, node, context) => {
|
|
2286
2600
|
return;
|
2287
2601
|
}
|
2288
2602
|
const expString = exp.content;
|
2289
|
-
if (!expString.trim() || !isMemberExpression(exp
|
2603
|
+
if (!expString.trim() || !isMemberExpression(exp)) {
|
2290
2604
|
context.options.onError(createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc));
|
2291
2605
|
return;
|
2292
2606
|
}
|
@@ -2297,7 +2611,7 @@ const transformVModel = (_dir, node, context) => {
|
|
2297
2611
|
model: true,
|
2298
2612
|
modelModifiers: dir.modifiers.map((m) => m.content)
|
2299
2613
|
};
|
2300
|
-
if (dir.arg) context.options.onError(
|
2614
|
+
if (dir.arg) context.options.onError(createCompilerError(ErrorCodes.X_V_MODEL_ARG_ON_ELEMENT, dir.arg.loc));
|
2301
2615
|
const tag = getText(node.openingElement.name, context);
|
2302
2616
|
const isCustomElement = context.options.isCustomElement(tag);
|
2303
2617
|
let modelType = "text";
|
@@ -2314,7 +2628,7 @@ const transformVModel = (_dir, node, context) => {
|
|
2314
2628
|
break;
|
2315
2629
|
case "file":
|
2316
2630
|
modelType = void 0;
|
2317
|
-
context.options.onError(
|
2631
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT, dir.loc));
|
2318
2632
|
break;
|
2319
2633
|
default:
|
2320
2634
|
checkDuplicatedValue();
|
@@ -2324,7 +2638,7 @@ const transformVModel = (_dir, node, context) => {
|
|
2324
2638
|
else checkDuplicatedValue();
|
2325
2639
|
} else if (tag === "select") modelType = "select";
|
2326
2640
|
else checkDuplicatedValue();
|
2327
|
-
else context.options.onError(
|
2641
|
+
else context.options.onError(createCompilerError(ErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT, dir.loc));
|
2328
2642
|
if (modelType) context.registerOperation({
|
2329
2643
|
type: IRNodeTypes.DIRECTIVE,
|
2330
2644
|
element: context.reference(),
|
@@ -2335,7 +2649,7 @@ const transformVModel = (_dir, node, context) => {
|
|
2335
2649
|
});
|
2336
2650
|
function checkDuplicatedValue() {
|
2337
2651
|
const value = findProp(node, "value");
|
2338
|
-
if (value && value.value?.type !== "StringLiteral") context.options.onError(
|
2652
|
+
if (value && value.value?.type !== "StringLiteral") context.options.onError(createCompilerError(ErrorCodes.X_V_MODEL_UNNECESSARY_VALUE, value.loc));
|
2339
2653
|
}
|
2340
2654
|
};
|
2341
2655
|
function hasDynamicKeyVBind(node) {
|
@@ -2350,10 +2664,10 @@ const transformVOn = (dir, node, context) => {
|
|
2350
2664
|
if (!name) return;
|
2351
2665
|
const isComponent = isJSXComponent(node);
|
2352
2666
|
const [nameString, ...modifiers] = context.ir.source.slice(name.start, name.end).replace(/^on([A-Z])/, (_, $1) => $1.toLowerCase()).split("_");
|
2353
|
-
if (!value && !modifiers.length) context.options.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION,
|
2354
|
-
let arg =
|
2667
|
+
if (!value && !modifiers.length) context.options.onError(createCompilerError(ErrorCodes.X_V_ON_NO_EXPRESSION, loc));
|
2668
|
+
let arg = createSimpleExpression(nameString, true, dir.name);
|
2355
2669
|
const exp = resolveExpression(dir.value, context);
|
2356
|
-
const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = resolveModifiers(arg.isStatic ? `on${nameString}` : arg, modifiers.map((modifier) => createSimpleExpression(modifier))
|
2670
|
+
const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = resolveModifiers(arg.isStatic ? `on${nameString}` : arg, modifiers.map((modifier) => createSimpleExpression(modifier)));
|
2357
2671
|
let keyOverride;
|
2358
2672
|
const isStaticClick = arg.isStatic && arg.content.toLowerCase() === "click";
|
2359
2673
|
if (nonKeyModifiers.includes("middle")) {
|
@@ -2395,6 +2709,35 @@ const transformVOn = (dir, node, context) => {
|
|
2395
2709
|
};
|
2396
2710
|
context.registerEffect([arg], operation);
|
2397
2711
|
};
|
2712
|
+
const isEventOptionModifier = /* @__PURE__ */ makeMap(`passive,once,capture`);
|
2713
|
+
const isNonKeyModifier = /* @__PURE__ */ makeMap("stop,prevent,self,ctrl,shift,alt,meta,exact,middle");
|
2714
|
+
const maybeKeyModifier = /* @__PURE__ */ makeMap("left,right");
|
2715
|
+
const isKeyboardEvent = /* @__PURE__ */ makeMap(`onkeyup,onkeydown,onkeypress`);
|
2716
|
+
const resolveModifiers = (key, modifiers) => {
|
2717
|
+
const keyModifiers = [];
|
2718
|
+
const nonKeyModifiers = [];
|
2719
|
+
const eventOptionModifiers = [];
|
2720
|
+
for (const modifier_ of modifiers) {
|
2721
|
+
const modifier = modifier_.content;
|
2722
|
+
if (isEventOptionModifier(modifier)) eventOptionModifiers.push(modifier);
|
2723
|
+
else {
|
2724
|
+
const keyString = isString(key) ? key : key.isStatic ? key.content : null;
|
2725
|
+
if (maybeKeyModifier(modifier)) if (keyString) if (isKeyboardEvent(keyString.toLowerCase())) keyModifiers.push(modifier);
|
2726
|
+
else nonKeyModifiers.push(modifier);
|
2727
|
+
else {
|
2728
|
+
keyModifiers.push(modifier);
|
2729
|
+
nonKeyModifiers.push(modifier);
|
2730
|
+
}
|
2731
|
+
else if (isNonKeyModifier(modifier)) nonKeyModifiers.push(modifier);
|
2732
|
+
else keyModifiers.push(modifier);
|
2733
|
+
}
|
2734
|
+
}
|
2735
|
+
return {
|
2736
|
+
keyModifiers,
|
2737
|
+
nonKeyModifiers,
|
2738
|
+
eventOptionModifiers
|
2739
|
+
};
|
2740
|
+
};
|
2398
2741
|
|
2399
2742
|
//#endregion
|
2400
2743
|
//#region src/transforms/vOnce.ts
|
@@ -2408,7 +2751,7 @@ const transformVShow = (_dir, node, context) => {
|
|
2408
2751
|
const dir = resolveDirective(_dir, context);
|
2409
2752
|
const { exp, loc } = dir;
|
2410
2753
|
if (!exp) {
|
2411
|
-
context.options.onError(
|
2754
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_SHOW_NO_EXPRESSION, loc));
|
2412
2755
|
return;
|
2413
2756
|
}
|
2414
2757
|
context.registerOperation({
|
@@ -2426,13 +2769,13 @@ const transformVSlot = (node, context) => {
|
|
2426
2769
|
if (node.type !== "JSXElement") return;
|
2427
2770
|
const { children } = node;
|
2428
2771
|
const dir = findProp(node, "v-slot");
|
2429
|
-
const resolvedDirective = dir ? resolveDirective(dir, context
|
2772
|
+
const resolvedDirective = dir ? resolveDirective(dir, context) : void 0;
|
2430
2773
|
const { parent } = context;
|
2431
2774
|
const isComponent = isJSXComponent(node);
|
2432
2775
|
const isSlotTemplate = isTemplate(node) && parent && parent.node.type === "JSXElement" && isJSXComponent(parent.node);
|
2433
2776
|
if (isComponent && children.length) return transformComponentSlot(node, resolvedDirective, context);
|
2434
2777
|
else if (isSlotTemplate && resolvedDirective) return transformTemplateSlot(node, resolvedDirective, context);
|
2435
|
-
else if (!isComponent && dir) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED,
|
2778
|
+
else if (!isComponent && dir) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, dir.loc));
|
2436
2779
|
};
|
2437
2780
|
function transformComponentSlot(node, dir, context) {
|
2438
2781
|
const { children } = node;
|
@@ -2447,7 +2790,7 @@ function transformComponentSlot(node, dir, context) {
|
|
2447
2790
|
context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, dir.loc));
|
2448
2791
|
return;
|
2449
2792
|
}
|
2450
|
-
if (nonSlotTemplateChildren.length) if (hasStaticSlot(slots, "default")) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,
|
2793
|
+
if (nonSlotTemplateChildren.length) if (hasStaticSlot(slots, "default")) context.options.onError(createCompilerError(ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN, nonSlotTemplateChildren[0].loc));
|
2451
2794
|
else {
|
2452
2795
|
registerSlot(slots, arg, block);
|
2453
2796
|
context.slots = slots;
|
@@ -2458,7 +2801,7 @@ function transformComponentSlot(node, dir, context) {
|
|
2458
2801
|
const elseIfRE = /^v-else(-if)?$/;
|
2459
2802
|
function transformTemplateSlot(node, dir, context) {
|
2460
2803
|
context.dynamic.flags |= DynamicFlag.NON_TEMPLATE;
|
2461
|
-
const arg = dir.arg
|
2804
|
+
const arg = dir.arg;
|
2462
2805
|
const vFor = findProp(node, "v-for");
|
2463
2806
|
const vIf = findProp(node, "v-if");
|
2464
2807
|
const vElse = findProp(node, elseIfRE);
|
@@ -2557,18 +2900,17 @@ const transformVSlots = (dir, node, context) => {
|
|
2557
2900
|
//#region src/transforms/vText.ts
|
2558
2901
|
const transformVText = (dir, node, context) => {
|
2559
2902
|
let exp;
|
2560
|
-
const loc = resolveLocation(dir.loc, context);
|
2561
2903
|
if (!dir.value) {
|
2562
|
-
context.options.onError(
|
2904
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_TEXT_NO_EXPRESSION, dir.loc));
|
2563
2905
|
exp = EMPTY_EXPRESSION;
|
2564
2906
|
} else exp = resolveExpression(dir.value, context);
|
2565
2907
|
if (node.children.length) {
|
2566
|
-
context.options.onError(
|
2908
|
+
context.options.onError(createCompilerError(ErrorCodes.X_V_TEXT_WITH_CHILDREN, dir.loc));
|
2567
2909
|
context.childrenTemplate.length = 0;
|
2568
2910
|
}
|
2569
2911
|
if (isVoidTag(getText(node.openingElement.name, context))) return;
|
2570
2912
|
const literal = getLiteralExpressionValue(exp);
|
2571
|
-
if (literal != null) context.childrenTemplate = [String(literal)];
|
2913
|
+
if (literal != null) context.childrenTemplate = [escapeHtml(String(literal))];
|
2572
2914
|
else {
|
2573
2915
|
context.childrenTemplate = [" "];
|
2574
2916
|
context.registerOperation({
|