@vue/compiler-dom 3.2.40 → 3.2.42
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-dom.cjs.js +852 -852
- package/dist/compiler-dom.cjs.prod.js +792 -792
- package/dist/compiler-dom.esm-browser.js +5453 -5426
- package/dist/compiler-dom.esm-browser.prod.js +1 -1
- package/dist/compiler-dom.esm-bundler.js +452 -452
- package/dist/compiler-dom.global.js +5453 -5425
- package/dist/compiler-dom.global.prod.js +1 -1
- package/package.json +3 -3
package/dist/compiler-dom.cjs.js
CHANGED
|
@@ -5,27 +5,27 @@ Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
5
5
|
var compilerCore = require('@vue/compiler-core');
|
|
6
6
|
var shared = require('@vue/shared');
|
|
7
7
|
|
|
8
|
-
const V_MODEL_RADIO = Symbol(`vModelRadio` );
|
|
9
|
-
const V_MODEL_CHECKBOX = Symbol(`vModelCheckbox` );
|
|
10
|
-
const V_MODEL_TEXT = Symbol(`vModelText` );
|
|
11
|
-
const V_MODEL_SELECT = Symbol(`vModelSelect` );
|
|
12
|
-
const V_MODEL_DYNAMIC = Symbol(`vModelDynamic` );
|
|
13
|
-
const V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard` );
|
|
14
|
-
const V_ON_WITH_KEYS = Symbol(`vOnKeysGuard` );
|
|
15
|
-
const V_SHOW = Symbol(`vShow` );
|
|
16
|
-
const TRANSITION = Symbol(`Transition` );
|
|
17
|
-
const TRANSITION_GROUP = Symbol(`TransitionGroup` );
|
|
18
|
-
compilerCore.registerRuntimeHelpers({
|
|
19
|
-
[V_MODEL_RADIO]: `vModelRadio`,
|
|
20
|
-
[V_MODEL_CHECKBOX]: `vModelCheckbox`,
|
|
21
|
-
[V_MODEL_TEXT]: `vModelText`,
|
|
22
|
-
[V_MODEL_SELECT]: `vModelSelect`,
|
|
23
|
-
[V_MODEL_DYNAMIC]: `vModelDynamic`,
|
|
24
|
-
[V_ON_WITH_MODIFIERS]: `withModifiers`,
|
|
25
|
-
[V_ON_WITH_KEYS]: `withKeys`,
|
|
26
|
-
[V_SHOW]: `vShow`,
|
|
27
|
-
[TRANSITION]: `Transition`,
|
|
28
|
-
[TRANSITION_GROUP]: `TransitionGroup`
|
|
8
|
+
const V_MODEL_RADIO = Symbol(`vModelRadio` );
|
|
9
|
+
const V_MODEL_CHECKBOX = Symbol(`vModelCheckbox` );
|
|
10
|
+
const V_MODEL_TEXT = Symbol(`vModelText` );
|
|
11
|
+
const V_MODEL_SELECT = Symbol(`vModelSelect` );
|
|
12
|
+
const V_MODEL_DYNAMIC = Symbol(`vModelDynamic` );
|
|
13
|
+
const V_ON_WITH_MODIFIERS = Symbol(`vOnModifiersGuard` );
|
|
14
|
+
const V_ON_WITH_KEYS = Symbol(`vOnKeysGuard` );
|
|
15
|
+
const V_SHOW = Symbol(`vShow` );
|
|
16
|
+
const TRANSITION = Symbol(`Transition` );
|
|
17
|
+
const TRANSITION_GROUP = Symbol(`TransitionGroup` );
|
|
18
|
+
compilerCore.registerRuntimeHelpers({
|
|
19
|
+
[V_MODEL_RADIO]: `vModelRadio`,
|
|
20
|
+
[V_MODEL_CHECKBOX]: `vModelCheckbox`,
|
|
21
|
+
[V_MODEL_TEXT]: `vModelText`,
|
|
22
|
+
[V_MODEL_SELECT]: `vModelSelect`,
|
|
23
|
+
[V_MODEL_DYNAMIC]: `vModelDynamic`,
|
|
24
|
+
[V_ON_WITH_MODIFIERS]: `withModifiers`,
|
|
25
|
+
[V_ON_WITH_KEYS]: `withKeys`,
|
|
26
|
+
[V_SHOW]: `vShow`,
|
|
27
|
+
[TRANSITION]: `Transition`,
|
|
28
|
+
[TRANSITION_GROUP]: `TransitionGroup`
|
|
29
29
|
});
|
|
30
30
|
|
|
31
31
|
var namedCharacterReferences = {
|
|
@@ -2262,861 +2262,861 @@ var namedCharacterReferences = {
|
|
|
2262
2262
|
"CounterClockwiseContourIntegral;": "∳"
|
|
2263
2263
|
};
|
|
2264
2264
|
|
|
2265
|
-
// lazy compute this to make this file tree-shakable for browser
|
|
2266
|
-
let maxCRNameLength;
|
|
2267
|
-
const decodeHtml = (rawText, asAttr) => {
|
|
2268
|
-
let offset = 0;
|
|
2269
|
-
const end = rawText.length;
|
|
2270
|
-
let decodedText = '';
|
|
2271
|
-
function advance(length) {
|
|
2272
|
-
offset += length;
|
|
2273
|
-
rawText = rawText.slice(length);
|
|
2274
|
-
}
|
|
2275
|
-
while (offset < end) {
|
|
2276
|
-
const head = /&(?:#x?)?/i.exec(rawText);
|
|
2277
|
-
if (!head || offset + head.index >= end) {
|
|
2278
|
-
const remaining = end - offset;
|
|
2279
|
-
decodedText += rawText.slice(0, remaining);
|
|
2280
|
-
advance(remaining);
|
|
2281
|
-
break;
|
|
2282
|
-
}
|
|
2283
|
-
// Advance to the "&".
|
|
2284
|
-
decodedText += rawText.slice(0, head.index);
|
|
2285
|
-
advance(head.index);
|
|
2286
|
-
if (head[0] === '&') {
|
|
2287
|
-
// Named character reference.
|
|
2288
|
-
let name = '';
|
|
2289
|
-
let value = undefined;
|
|
2290
|
-
if (/[0-9a-z]/i.test(rawText[1])) {
|
|
2291
|
-
if (!maxCRNameLength) {
|
|
2292
|
-
maxCRNameLength = Object.keys(namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0);
|
|
2293
|
-
}
|
|
2294
|
-
for (let length = maxCRNameLength; !value && length > 0; --length) {
|
|
2295
|
-
name = rawText.slice(1, 1 + length);
|
|
2296
|
-
value = namedCharacterReferences[name];
|
|
2297
|
-
}
|
|
2298
|
-
if (value) {
|
|
2299
|
-
const semi = name.endsWith(';');
|
|
2300
|
-
if (asAttr &&
|
|
2301
|
-
!semi &&
|
|
2302
|
-
/[=a-z0-9]/i.test(rawText[name.length + 1] || '')) {
|
|
2303
|
-
decodedText += '&' + name;
|
|
2304
|
-
advance(1 + name.length);
|
|
2305
|
-
}
|
|
2306
|
-
else {
|
|
2307
|
-
decodedText += value;
|
|
2308
|
-
advance(1 + name.length);
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
else {
|
|
2312
|
-
decodedText += '&' + name;
|
|
2313
|
-
advance(1 + name.length);
|
|
2314
|
-
}
|
|
2315
|
-
}
|
|
2316
|
-
else {
|
|
2317
|
-
decodedText += '&';
|
|
2318
|
-
advance(1);
|
|
2319
|
-
}
|
|
2320
|
-
}
|
|
2321
|
-
else {
|
|
2322
|
-
// Numeric character reference.
|
|
2323
|
-
const hex = head[0] === '&#x';
|
|
2324
|
-
const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;
|
|
2325
|
-
const body = pattern.exec(rawText);
|
|
2326
|
-
if (!body) {
|
|
2327
|
-
decodedText += head[0];
|
|
2328
|
-
advance(head[0].length);
|
|
2329
|
-
}
|
|
2330
|
-
else {
|
|
2331
|
-
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
|
|
2332
|
-
let cp = Number.parseInt(body[1], hex ? 16 : 10);
|
|
2333
|
-
if (cp === 0) {
|
|
2334
|
-
cp = 0xfffd;
|
|
2335
|
-
}
|
|
2336
|
-
else if (cp > 0x10ffff) {
|
|
2337
|
-
cp = 0xfffd;
|
|
2338
|
-
}
|
|
2339
|
-
else if (cp >= 0xd800 && cp <= 0xdfff) {
|
|
2340
|
-
cp = 0xfffd;
|
|
2341
|
-
}
|
|
2342
|
-
else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) ;
|
|
2343
|
-
else if ((cp >= 0x01 && cp <= 0x08) ||
|
|
2344
|
-
cp === 0x0b ||
|
|
2345
|
-
(cp >= 0x0d && cp <= 0x1f) ||
|
|
2346
|
-
(cp >= 0x7f && cp <= 0x9f)) {
|
|
2347
|
-
cp = CCR_REPLACEMENTS[cp] || cp;
|
|
2348
|
-
}
|
|
2349
|
-
decodedText += String.fromCodePoint(cp);
|
|
2350
|
-
advance(body[0].length);
|
|
2351
|
-
}
|
|
2352
|
-
}
|
|
2353
|
-
}
|
|
2354
|
-
return decodedText;
|
|
2355
|
-
};
|
|
2356
|
-
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
|
|
2357
|
-
const CCR_REPLACEMENTS = {
|
|
2358
|
-
0x80: 0x20ac,
|
|
2359
|
-
0x82: 0x201a,
|
|
2360
|
-
0x83: 0x0192,
|
|
2361
|
-
0x84: 0x201e,
|
|
2362
|
-
0x85: 0x2026,
|
|
2363
|
-
0x86: 0x2020,
|
|
2364
|
-
0x87: 0x2021,
|
|
2365
|
-
0x88: 0x02c6,
|
|
2366
|
-
0x89: 0x2030,
|
|
2367
|
-
0x8a: 0x0160,
|
|
2368
|
-
0x8b: 0x2039,
|
|
2369
|
-
0x8c: 0x0152,
|
|
2370
|
-
0x8e: 0x017d,
|
|
2371
|
-
0x91: 0x2018,
|
|
2372
|
-
0x92: 0x2019,
|
|
2373
|
-
0x93: 0x201c,
|
|
2374
|
-
0x94: 0x201d,
|
|
2375
|
-
0x95: 0x2022,
|
|
2376
|
-
0x96: 0x2013,
|
|
2377
|
-
0x97: 0x2014,
|
|
2378
|
-
0x98: 0x02dc,
|
|
2379
|
-
0x99: 0x2122,
|
|
2380
|
-
0x9a: 0x0161,
|
|
2381
|
-
0x9b: 0x203a,
|
|
2382
|
-
0x9c: 0x0153,
|
|
2383
|
-
0x9e: 0x017e,
|
|
2384
|
-
0x9f: 0x0178
|
|
2265
|
+
// lazy compute this to make this file tree-shakable for browser
|
|
2266
|
+
let maxCRNameLength;
|
|
2267
|
+
const decodeHtml = (rawText, asAttr) => {
|
|
2268
|
+
let offset = 0;
|
|
2269
|
+
const end = rawText.length;
|
|
2270
|
+
let decodedText = '';
|
|
2271
|
+
function advance(length) {
|
|
2272
|
+
offset += length;
|
|
2273
|
+
rawText = rawText.slice(length);
|
|
2274
|
+
}
|
|
2275
|
+
while (offset < end) {
|
|
2276
|
+
const head = /&(?:#x?)?/i.exec(rawText);
|
|
2277
|
+
if (!head || offset + head.index >= end) {
|
|
2278
|
+
const remaining = end - offset;
|
|
2279
|
+
decodedText += rawText.slice(0, remaining);
|
|
2280
|
+
advance(remaining);
|
|
2281
|
+
break;
|
|
2282
|
+
}
|
|
2283
|
+
// Advance to the "&".
|
|
2284
|
+
decodedText += rawText.slice(0, head.index);
|
|
2285
|
+
advance(head.index);
|
|
2286
|
+
if (head[0] === '&') {
|
|
2287
|
+
// Named character reference.
|
|
2288
|
+
let name = '';
|
|
2289
|
+
let value = undefined;
|
|
2290
|
+
if (/[0-9a-z]/i.test(rawText[1])) {
|
|
2291
|
+
if (!maxCRNameLength) {
|
|
2292
|
+
maxCRNameLength = Object.keys(namedCharacterReferences).reduce((max, name) => Math.max(max, name.length), 0);
|
|
2293
|
+
}
|
|
2294
|
+
for (let length = maxCRNameLength; !value && length > 0; --length) {
|
|
2295
|
+
name = rawText.slice(1, 1 + length);
|
|
2296
|
+
value = namedCharacterReferences[name];
|
|
2297
|
+
}
|
|
2298
|
+
if (value) {
|
|
2299
|
+
const semi = name.endsWith(';');
|
|
2300
|
+
if (asAttr &&
|
|
2301
|
+
!semi &&
|
|
2302
|
+
/[=a-z0-9]/i.test(rawText[name.length + 1] || '')) {
|
|
2303
|
+
decodedText += '&' + name;
|
|
2304
|
+
advance(1 + name.length);
|
|
2305
|
+
}
|
|
2306
|
+
else {
|
|
2307
|
+
decodedText += value;
|
|
2308
|
+
advance(1 + name.length);
|
|
2309
|
+
}
|
|
2310
|
+
}
|
|
2311
|
+
else {
|
|
2312
|
+
decodedText += '&' + name;
|
|
2313
|
+
advance(1 + name.length);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
else {
|
|
2317
|
+
decodedText += '&';
|
|
2318
|
+
advance(1);
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
else {
|
|
2322
|
+
// Numeric character reference.
|
|
2323
|
+
const hex = head[0] === '&#x';
|
|
2324
|
+
const pattern = hex ? /^&#x([0-9a-f]+);?/i : /^&#([0-9]+);?/;
|
|
2325
|
+
const body = pattern.exec(rawText);
|
|
2326
|
+
if (!body) {
|
|
2327
|
+
decodedText += head[0];
|
|
2328
|
+
advance(head[0].length);
|
|
2329
|
+
}
|
|
2330
|
+
else {
|
|
2331
|
+
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
|
|
2332
|
+
let cp = Number.parseInt(body[1], hex ? 16 : 10);
|
|
2333
|
+
if (cp === 0) {
|
|
2334
|
+
cp = 0xfffd;
|
|
2335
|
+
}
|
|
2336
|
+
else if (cp > 0x10ffff) {
|
|
2337
|
+
cp = 0xfffd;
|
|
2338
|
+
}
|
|
2339
|
+
else if (cp >= 0xd800 && cp <= 0xdfff) {
|
|
2340
|
+
cp = 0xfffd;
|
|
2341
|
+
}
|
|
2342
|
+
else if ((cp >= 0xfdd0 && cp <= 0xfdef) || (cp & 0xfffe) === 0xfffe) ;
|
|
2343
|
+
else if ((cp >= 0x01 && cp <= 0x08) ||
|
|
2344
|
+
cp === 0x0b ||
|
|
2345
|
+
(cp >= 0x0d && cp <= 0x1f) ||
|
|
2346
|
+
(cp >= 0x7f && cp <= 0x9f)) {
|
|
2347
|
+
cp = CCR_REPLACEMENTS[cp] || cp;
|
|
2348
|
+
}
|
|
2349
|
+
decodedText += String.fromCodePoint(cp);
|
|
2350
|
+
advance(body[0].length);
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2353
|
+
}
|
|
2354
|
+
return decodedText;
|
|
2355
|
+
};
|
|
2356
|
+
// https://html.spec.whatwg.org/multipage/parsing.html#numeric-character-reference-end-state
|
|
2357
|
+
const CCR_REPLACEMENTS = {
|
|
2358
|
+
0x80: 0x20ac,
|
|
2359
|
+
0x82: 0x201a,
|
|
2360
|
+
0x83: 0x0192,
|
|
2361
|
+
0x84: 0x201e,
|
|
2362
|
+
0x85: 0x2026,
|
|
2363
|
+
0x86: 0x2020,
|
|
2364
|
+
0x87: 0x2021,
|
|
2365
|
+
0x88: 0x02c6,
|
|
2366
|
+
0x89: 0x2030,
|
|
2367
|
+
0x8a: 0x0160,
|
|
2368
|
+
0x8b: 0x2039,
|
|
2369
|
+
0x8c: 0x0152,
|
|
2370
|
+
0x8e: 0x017d,
|
|
2371
|
+
0x91: 0x2018,
|
|
2372
|
+
0x92: 0x2019,
|
|
2373
|
+
0x93: 0x201c,
|
|
2374
|
+
0x94: 0x201d,
|
|
2375
|
+
0x95: 0x2022,
|
|
2376
|
+
0x96: 0x2013,
|
|
2377
|
+
0x97: 0x2014,
|
|
2378
|
+
0x98: 0x02dc,
|
|
2379
|
+
0x99: 0x2122,
|
|
2380
|
+
0x9a: 0x0161,
|
|
2381
|
+
0x9b: 0x203a,
|
|
2382
|
+
0x9c: 0x0153,
|
|
2383
|
+
0x9e: 0x017e,
|
|
2384
|
+
0x9f: 0x0178
|
|
2385
2385
|
};
|
|
2386
2386
|
|
|
2387
|
-
const isRawTextContainer = /*#__PURE__*/ shared.makeMap('style,iframe,script,noscript', true);
|
|
2388
|
-
const parserOptions = {
|
|
2389
|
-
isVoidTag: shared.isVoidTag,
|
|
2390
|
-
isNativeTag: tag => shared.isHTMLTag(tag) || shared.isSVGTag(tag),
|
|
2391
|
-
isPreTag: tag => tag === 'pre',
|
|
2392
|
-
decodeEntities: decodeHtml,
|
|
2393
|
-
isBuiltInComponent: (tag) => {
|
|
2394
|
-
if (compilerCore.isBuiltInType(tag, `Transition`)) {
|
|
2395
|
-
return TRANSITION;
|
|
2396
|
-
}
|
|
2397
|
-
else if (compilerCore.isBuiltInType(tag, `TransitionGroup`)) {
|
|
2398
|
-
return TRANSITION_GROUP;
|
|
2399
|
-
}
|
|
2400
|
-
},
|
|
2401
|
-
// https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher
|
|
2402
|
-
getNamespace(tag, parent) {
|
|
2403
|
-
let ns = parent ? parent.ns : 0 /* DOMNamespaces.HTML */;
|
|
2404
|
-
if (parent && ns === 2 /* DOMNamespaces.MATH_ML */) {
|
|
2405
|
-
if (parent.tag === 'annotation-xml') {
|
|
2406
|
-
if (tag === 'svg') {
|
|
2407
|
-
return 1 /* DOMNamespaces.SVG */;
|
|
2408
|
-
}
|
|
2409
|
-
if (parent.props.some(a => a.type === 6 /* NodeTypes.ATTRIBUTE */ &&
|
|
2410
|
-
a.name === 'encoding' &&
|
|
2411
|
-
a.value != null &&
|
|
2412
|
-
(a.value.content === 'text/html' ||
|
|
2413
|
-
a.value.content === 'application/xhtml+xml'))) {
|
|
2414
|
-
ns = 0 /* DOMNamespaces.HTML */;
|
|
2415
|
-
}
|
|
2416
|
-
}
|
|
2417
|
-
else if (/^m(?:[ions]|text)$/.test(parent.tag) &&
|
|
2418
|
-
tag !== 'mglyph' &&
|
|
2419
|
-
tag !== 'malignmark') {
|
|
2420
|
-
ns = 0 /* DOMNamespaces.HTML */;
|
|
2421
|
-
}
|
|
2422
|
-
}
|
|
2423
|
-
else if (parent && ns === 1 /* DOMNamespaces.SVG */) {
|
|
2424
|
-
if (parent.tag === 'foreignObject' ||
|
|
2425
|
-
parent.tag === 'desc' ||
|
|
2426
|
-
parent.tag === 'title') {
|
|
2427
|
-
ns = 0 /* DOMNamespaces.HTML */;
|
|
2428
|
-
}
|
|
2429
|
-
}
|
|
2430
|
-
if (ns === 0 /* DOMNamespaces.HTML */) {
|
|
2431
|
-
if (tag === 'svg') {
|
|
2432
|
-
return 1 /* DOMNamespaces.SVG */;
|
|
2433
|
-
}
|
|
2434
|
-
if (tag === 'math') {
|
|
2435
|
-
return 2 /* DOMNamespaces.MATH_ML */;
|
|
2436
|
-
}
|
|
2437
|
-
}
|
|
2438
|
-
return ns;
|
|
2439
|
-
},
|
|
2440
|
-
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments
|
|
2441
|
-
getTextMode({ tag, ns }) {
|
|
2442
|
-
if (ns === 0 /* DOMNamespaces.HTML */) {
|
|
2443
|
-
if (tag === 'textarea' || tag === 'title') {
|
|
2444
|
-
return 1 /* TextModes.RCDATA */;
|
|
2445
|
-
}
|
|
2446
|
-
if (isRawTextContainer(tag)) {
|
|
2447
|
-
return 2 /* TextModes.RAWTEXT */;
|
|
2448
|
-
}
|
|
2449
|
-
}
|
|
2450
|
-
return 0 /* TextModes.DATA */;
|
|
2451
|
-
}
|
|
2387
|
+
const isRawTextContainer = /*#__PURE__*/ shared.makeMap('style,iframe,script,noscript', true);
|
|
2388
|
+
const parserOptions = {
|
|
2389
|
+
isVoidTag: shared.isVoidTag,
|
|
2390
|
+
isNativeTag: tag => shared.isHTMLTag(tag) || shared.isSVGTag(tag),
|
|
2391
|
+
isPreTag: tag => tag === 'pre',
|
|
2392
|
+
decodeEntities: decodeHtml,
|
|
2393
|
+
isBuiltInComponent: (tag) => {
|
|
2394
|
+
if (compilerCore.isBuiltInType(tag, `Transition`)) {
|
|
2395
|
+
return TRANSITION;
|
|
2396
|
+
}
|
|
2397
|
+
else if (compilerCore.isBuiltInType(tag, `TransitionGroup`)) {
|
|
2398
|
+
return TRANSITION_GROUP;
|
|
2399
|
+
}
|
|
2400
|
+
},
|
|
2401
|
+
// https://html.spec.whatwg.org/multipage/parsing.html#tree-construction-dispatcher
|
|
2402
|
+
getNamespace(tag, parent) {
|
|
2403
|
+
let ns = parent ? parent.ns : 0 /* DOMNamespaces.HTML */;
|
|
2404
|
+
if (parent && ns === 2 /* DOMNamespaces.MATH_ML */) {
|
|
2405
|
+
if (parent.tag === 'annotation-xml') {
|
|
2406
|
+
if (tag === 'svg') {
|
|
2407
|
+
return 1 /* DOMNamespaces.SVG */;
|
|
2408
|
+
}
|
|
2409
|
+
if (parent.props.some(a => a.type === 6 /* NodeTypes.ATTRIBUTE */ &&
|
|
2410
|
+
a.name === 'encoding' &&
|
|
2411
|
+
a.value != null &&
|
|
2412
|
+
(a.value.content === 'text/html' ||
|
|
2413
|
+
a.value.content === 'application/xhtml+xml'))) {
|
|
2414
|
+
ns = 0 /* DOMNamespaces.HTML */;
|
|
2415
|
+
}
|
|
2416
|
+
}
|
|
2417
|
+
else if (/^m(?:[ions]|text)$/.test(parent.tag) &&
|
|
2418
|
+
tag !== 'mglyph' &&
|
|
2419
|
+
tag !== 'malignmark') {
|
|
2420
|
+
ns = 0 /* DOMNamespaces.HTML */;
|
|
2421
|
+
}
|
|
2422
|
+
}
|
|
2423
|
+
else if (parent && ns === 1 /* DOMNamespaces.SVG */) {
|
|
2424
|
+
if (parent.tag === 'foreignObject' ||
|
|
2425
|
+
parent.tag === 'desc' ||
|
|
2426
|
+
parent.tag === 'title') {
|
|
2427
|
+
ns = 0 /* DOMNamespaces.HTML */;
|
|
2428
|
+
}
|
|
2429
|
+
}
|
|
2430
|
+
if (ns === 0 /* DOMNamespaces.HTML */) {
|
|
2431
|
+
if (tag === 'svg') {
|
|
2432
|
+
return 1 /* DOMNamespaces.SVG */;
|
|
2433
|
+
}
|
|
2434
|
+
if (tag === 'math') {
|
|
2435
|
+
return 2 /* DOMNamespaces.MATH_ML */;
|
|
2436
|
+
}
|
|
2437
|
+
}
|
|
2438
|
+
return ns;
|
|
2439
|
+
},
|
|
2440
|
+
// https://html.spec.whatwg.org/multipage/parsing.html#parsing-html-fragments
|
|
2441
|
+
getTextMode({ tag, ns }) {
|
|
2442
|
+
if (ns === 0 /* DOMNamespaces.HTML */) {
|
|
2443
|
+
if (tag === 'textarea' || tag === 'title') {
|
|
2444
|
+
return 1 /* TextModes.RCDATA */;
|
|
2445
|
+
}
|
|
2446
|
+
if (isRawTextContainer(tag)) {
|
|
2447
|
+
return 2 /* TextModes.RAWTEXT */;
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2450
|
+
return 0 /* TextModes.DATA */;
|
|
2451
|
+
}
|
|
2452
2452
|
};
|
|
2453
2453
|
|
|
2454
|
-
// Parse inline CSS strings for static style attributes into an object.
|
|
2455
|
-
// This is a NodeTransform since it works on the static `style` attribute and
|
|
2456
|
-
// converts it into a dynamic equivalent:
|
|
2457
|
-
// style="color: red" -> :style='{ "color": "red" }'
|
|
2458
|
-
// It is then processed by `transformElement` and included in the generated
|
|
2459
|
-
// props.
|
|
2460
|
-
const transformStyle = node => {
|
|
2461
|
-
if (node.type === 1 /* NodeTypes.ELEMENT */) {
|
|
2462
|
-
node.props.forEach((p, i) => {
|
|
2463
|
-
if (p.type === 6 /* NodeTypes.ATTRIBUTE */ && p.name === 'style' && p.value) {
|
|
2464
|
-
// replace p with an expression node
|
|
2465
|
-
node.props[i] = {
|
|
2466
|
-
type: 7 /* NodeTypes.DIRECTIVE */,
|
|
2467
|
-
name: `bind`,
|
|
2468
|
-
arg: compilerCore.createSimpleExpression(`style`, true, p.loc),
|
|
2469
|
-
exp: parseInlineCSS(p.value.content, p.loc),
|
|
2470
|
-
modifiers: [],
|
|
2471
|
-
loc: p.loc
|
|
2472
|
-
};
|
|
2473
|
-
}
|
|
2474
|
-
});
|
|
2475
|
-
}
|
|
2476
|
-
};
|
|
2477
|
-
const parseInlineCSS = (cssText, loc) => {
|
|
2478
|
-
const normalized = shared.parseStringStyle(cssText);
|
|
2479
|
-
return compilerCore.createSimpleExpression(JSON.stringify(normalized), false, loc, 3 /* ConstantTypes.CAN_STRINGIFY */);
|
|
2454
|
+
// Parse inline CSS strings for static style attributes into an object.
|
|
2455
|
+
// This is a NodeTransform since it works on the static `style` attribute and
|
|
2456
|
+
// converts it into a dynamic equivalent:
|
|
2457
|
+
// style="color: red" -> :style='{ "color": "red" }'
|
|
2458
|
+
// It is then processed by `transformElement` and included in the generated
|
|
2459
|
+
// props.
|
|
2460
|
+
const transformStyle = node => {
|
|
2461
|
+
if (node.type === 1 /* NodeTypes.ELEMENT */) {
|
|
2462
|
+
node.props.forEach((p, i) => {
|
|
2463
|
+
if (p.type === 6 /* NodeTypes.ATTRIBUTE */ && p.name === 'style' && p.value) {
|
|
2464
|
+
// replace p with an expression node
|
|
2465
|
+
node.props[i] = {
|
|
2466
|
+
type: 7 /* NodeTypes.DIRECTIVE */,
|
|
2467
|
+
name: `bind`,
|
|
2468
|
+
arg: compilerCore.createSimpleExpression(`style`, true, p.loc),
|
|
2469
|
+
exp: parseInlineCSS(p.value.content, p.loc),
|
|
2470
|
+
modifiers: [],
|
|
2471
|
+
loc: p.loc
|
|
2472
|
+
};
|
|
2473
|
+
}
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2476
|
+
};
|
|
2477
|
+
const parseInlineCSS = (cssText, loc) => {
|
|
2478
|
+
const normalized = shared.parseStringStyle(cssText);
|
|
2479
|
+
return compilerCore.createSimpleExpression(JSON.stringify(normalized), false, loc, 3 /* ConstantTypes.CAN_STRINGIFY */);
|
|
2480
2480
|
};
|
|
2481
2481
|
|
|
2482
|
-
function createDOMCompilerError(code, loc) {
|
|
2483
|
-
return compilerCore.createCompilerError(code, loc, DOMErrorMessages );
|
|
2484
|
-
}
|
|
2485
|
-
const DOMErrorMessages = {
|
|
2486
|
-
[50 /* DOMErrorCodes.X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`,
|
|
2487
|
-
[51 /* DOMErrorCodes.X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`,
|
|
2488
|
-
[52 /* DOMErrorCodes.X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`,
|
|
2489
|
-
[53 /* DOMErrorCodes.X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`,
|
|
2490
|
-
[54 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`,
|
|
2491
|
-
[55 /* DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`,
|
|
2492
|
-
[56 /* DOMErrorCodes.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.`,
|
|
2493
|
-
[57 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,
|
|
2494
|
-
[58 /* DOMErrorCodes.X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`,
|
|
2495
|
-
[59 /* DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`,
|
|
2496
|
-
[60 /* DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG */]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`
|
|
2482
|
+
function createDOMCompilerError(code, loc) {
|
|
2483
|
+
return compilerCore.createCompilerError(code, loc, DOMErrorMessages );
|
|
2484
|
+
}
|
|
2485
|
+
const DOMErrorMessages = {
|
|
2486
|
+
[50 /* DOMErrorCodes.X_V_HTML_NO_EXPRESSION */]: `v-html is missing expression.`,
|
|
2487
|
+
[51 /* DOMErrorCodes.X_V_HTML_WITH_CHILDREN */]: `v-html will override element children.`,
|
|
2488
|
+
[52 /* DOMErrorCodes.X_V_TEXT_NO_EXPRESSION */]: `v-text is missing expression.`,
|
|
2489
|
+
[53 /* DOMErrorCodes.X_V_TEXT_WITH_CHILDREN */]: `v-text will override element children.`,
|
|
2490
|
+
[54 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */]: `v-model can only be used on <input>, <textarea> and <select> elements.`,
|
|
2491
|
+
[55 /* DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT */]: `v-model argument is not supported on plain elements.`,
|
|
2492
|
+
[56 /* DOMErrorCodes.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.`,
|
|
2493
|
+
[57 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,
|
|
2494
|
+
[58 /* DOMErrorCodes.X_V_SHOW_NO_EXPRESSION */]: `v-show is missing expression.`,
|
|
2495
|
+
[59 /* DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN */]: `<Transition> expects exactly one child element or component.`,
|
|
2496
|
+
[60 /* DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG */]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`
|
|
2497
2497
|
};
|
|
2498
2498
|
|
|
2499
|
-
const transformVHtml = (dir, node, context) => {
|
|
2500
|
-
const { exp, loc } = dir;
|
|
2501
|
-
if (!exp) {
|
|
2502
|
-
context.onError(createDOMCompilerError(50 /* DOMErrorCodes.X_V_HTML_NO_EXPRESSION */, loc));
|
|
2503
|
-
}
|
|
2504
|
-
if (node.children.length) {
|
|
2505
|
-
context.onError(createDOMCompilerError(51 /* DOMErrorCodes.X_V_HTML_WITH_CHILDREN */, loc));
|
|
2506
|
-
node.children.length = 0;
|
|
2507
|
-
}
|
|
2508
|
-
return {
|
|
2509
|
-
props: [
|
|
2510
|
-
compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`innerHTML`, true, loc), exp || compilerCore.createSimpleExpression('', true))
|
|
2511
|
-
]
|
|
2512
|
-
};
|
|
2499
|
+
const transformVHtml = (dir, node, context) => {
|
|
2500
|
+
const { exp, loc } = dir;
|
|
2501
|
+
if (!exp) {
|
|
2502
|
+
context.onError(createDOMCompilerError(50 /* DOMErrorCodes.X_V_HTML_NO_EXPRESSION */, loc));
|
|
2503
|
+
}
|
|
2504
|
+
if (node.children.length) {
|
|
2505
|
+
context.onError(createDOMCompilerError(51 /* DOMErrorCodes.X_V_HTML_WITH_CHILDREN */, loc));
|
|
2506
|
+
node.children.length = 0;
|
|
2507
|
+
}
|
|
2508
|
+
return {
|
|
2509
|
+
props: [
|
|
2510
|
+
compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`innerHTML`, true, loc), exp || compilerCore.createSimpleExpression('', true))
|
|
2511
|
+
]
|
|
2512
|
+
};
|
|
2513
2513
|
};
|
|
2514
2514
|
|
|
2515
|
-
const transformVText = (dir, node, context) => {
|
|
2516
|
-
const { exp, loc } = dir;
|
|
2517
|
-
if (!exp) {
|
|
2518
|
-
context.onError(createDOMCompilerError(52 /* DOMErrorCodes.X_V_TEXT_NO_EXPRESSION */, loc));
|
|
2519
|
-
}
|
|
2520
|
-
if (node.children.length) {
|
|
2521
|
-
context.onError(createDOMCompilerError(53 /* DOMErrorCodes.X_V_TEXT_WITH_CHILDREN */, loc));
|
|
2522
|
-
node.children.length = 0;
|
|
2523
|
-
}
|
|
2524
|
-
return {
|
|
2525
|
-
props: [
|
|
2526
|
-
compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`textContent`, true), exp
|
|
2527
|
-
? compilerCore.getConstantType(exp, context) > 0
|
|
2528
|
-
? exp
|
|
2529
|
-
: compilerCore.createCallExpression(context.helperString(compilerCore.TO_DISPLAY_STRING), [exp], loc)
|
|
2530
|
-
: compilerCore.createSimpleExpression('', true))
|
|
2531
|
-
]
|
|
2532
|
-
};
|
|
2515
|
+
const transformVText = (dir, node, context) => {
|
|
2516
|
+
const { exp, loc } = dir;
|
|
2517
|
+
if (!exp) {
|
|
2518
|
+
context.onError(createDOMCompilerError(52 /* DOMErrorCodes.X_V_TEXT_NO_EXPRESSION */, loc));
|
|
2519
|
+
}
|
|
2520
|
+
if (node.children.length) {
|
|
2521
|
+
context.onError(createDOMCompilerError(53 /* DOMErrorCodes.X_V_TEXT_WITH_CHILDREN */, loc));
|
|
2522
|
+
node.children.length = 0;
|
|
2523
|
+
}
|
|
2524
|
+
return {
|
|
2525
|
+
props: [
|
|
2526
|
+
compilerCore.createObjectProperty(compilerCore.createSimpleExpression(`textContent`, true), exp
|
|
2527
|
+
? compilerCore.getConstantType(exp, context) > 0
|
|
2528
|
+
? exp
|
|
2529
|
+
: compilerCore.createCallExpression(context.helperString(compilerCore.TO_DISPLAY_STRING), [exp], loc)
|
|
2530
|
+
: compilerCore.createSimpleExpression('', true))
|
|
2531
|
+
]
|
|
2532
|
+
};
|
|
2533
2533
|
};
|
|
2534
2534
|
|
|
2535
|
-
const transformModel = (dir, node, context) => {
|
|
2536
|
-
const baseResult = compilerCore.transformModel(dir, node, context);
|
|
2537
|
-
// base transform has errors OR component v-model (only need props)
|
|
2538
|
-
if (!baseResult.props.length || node.tagType === 1 /* ElementTypes.COMPONENT */) {
|
|
2539
|
-
return baseResult;
|
|
2540
|
-
}
|
|
2541
|
-
if (dir.arg) {
|
|
2542
|
-
context.onError(createDOMCompilerError(55 /* DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));
|
|
2543
|
-
}
|
|
2544
|
-
function checkDuplicatedValue() {
|
|
2545
|
-
const value = compilerCore.findProp(node, 'value');
|
|
2546
|
-
if (value) {
|
|
2547
|
-
context.onError(createDOMCompilerError(57 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */, value.loc));
|
|
2548
|
-
}
|
|
2549
|
-
}
|
|
2550
|
-
const { tag } = node;
|
|
2551
|
-
const isCustomElement = context.isCustomElement(tag);
|
|
2552
|
-
if (tag === 'input' ||
|
|
2553
|
-
tag === 'textarea' ||
|
|
2554
|
-
tag === 'select' ||
|
|
2555
|
-
isCustomElement) {
|
|
2556
|
-
let directiveToUse = V_MODEL_TEXT;
|
|
2557
|
-
let isInvalidType = false;
|
|
2558
|
-
if (tag === 'input' || isCustomElement) {
|
|
2559
|
-
const type = compilerCore.findProp(node, `type`);
|
|
2560
|
-
if (type) {
|
|
2561
|
-
if (type.type === 7 /* NodeTypes.DIRECTIVE */) {
|
|
2562
|
-
// :type="foo"
|
|
2563
|
-
directiveToUse = V_MODEL_DYNAMIC;
|
|
2564
|
-
}
|
|
2565
|
-
else if (type.value) {
|
|
2566
|
-
switch (type.value.content) {
|
|
2567
|
-
case 'radio':
|
|
2568
|
-
directiveToUse = V_MODEL_RADIO;
|
|
2569
|
-
break;
|
|
2570
|
-
case 'checkbox':
|
|
2571
|
-
directiveToUse = V_MODEL_CHECKBOX;
|
|
2572
|
-
break;
|
|
2573
|
-
case 'file':
|
|
2574
|
-
isInvalidType = true;
|
|
2575
|
-
context.onError(createDOMCompilerError(56 /* DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));
|
|
2576
|
-
break;
|
|
2577
|
-
default:
|
|
2578
|
-
// text type
|
|
2579
|
-
checkDuplicatedValue();
|
|
2580
|
-
break;
|
|
2581
|
-
}
|
|
2582
|
-
}
|
|
2583
|
-
}
|
|
2584
|
-
else if (compilerCore.hasDynamicKeyVBind(node)) {
|
|
2585
|
-
// element has bindings with dynamic keys, which can possibly contain
|
|
2586
|
-
// "type".
|
|
2587
|
-
directiveToUse = V_MODEL_DYNAMIC;
|
|
2588
|
-
}
|
|
2589
|
-
else {
|
|
2590
|
-
// text type
|
|
2591
|
-
checkDuplicatedValue();
|
|
2592
|
-
}
|
|
2593
|
-
}
|
|
2594
|
-
else if (tag === 'select') {
|
|
2595
|
-
directiveToUse = V_MODEL_SELECT;
|
|
2596
|
-
}
|
|
2597
|
-
else {
|
|
2598
|
-
// textarea
|
|
2599
|
-
checkDuplicatedValue();
|
|
2600
|
-
}
|
|
2601
|
-
// inject runtime directive
|
|
2602
|
-
// by returning the helper symbol via needRuntime
|
|
2603
|
-
// the import will replaced a resolveDirective call.
|
|
2604
|
-
if (!isInvalidType) {
|
|
2605
|
-
baseResult.needRuntime = context.helper(directiveToUse);
|
|
2606
|
-
}
|
|
2607
|
-
}
|
|
2608
|
-
else {
|
|
2609
|
-
context.onError(createDOMCompilerError(54 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));
|
|
2610
|
-
}
|
|
2611
|
-
// native vmodel doesn't need the `modelValue` props since they are also
|
|
2612
|
-
// passed to the runtime as `binding.value`. removing it reduces code size.
|
|
2613
|
-
baseResult.props = baseResult.props.filter(p => !(p.key.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
|
|
2614
|
-
p.key.content === 'modelValue'));
|
|
2615
|
-
return baseResult;
|
|
2535
|
+
const transformModel = (dir, node, context) => {
|
|
2536
|
+
const baseResult = compilerCore.transformModel(dir, node, context);
|
|
2537
|
+
// base transform has errors OR component v-model (only need props)
|
|
2538
|
+
if (!baseResult.props.length || node.tagType === 1 /* ElementTypes.COMPONENT */) {
|
|
2539
|
+
return baseResult;
|
|
2540
|
+
}
|
|
2541
|
+
if (dir.arg) {
|
|
2542
|
+
context.onError(createDOMCompilerError(55 /* DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT */, dir.arg.loc));
|
|
2543
|
+
}
|
|
2544
|
+
function checkDuplicatedValue() {
|
|
2545
|
+
const value = compilerCore.findProp(node, 'value');
|
|
2546
|
+
if (value) {
|
|
2547
|
+
context.onError(createDOMCompilerError(57 /* DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE */, value.loc));
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
const { tag } = node;
|
|
2551
|
+
const isCustomElement = context.isCustomElement(tag);
|
|
2552
|
+
if (tag === 'input' ||
|
|
2553
|
+
tag === 'textarea' ||
|
|
2554
|
+
tag === 'select' ||
|
|
2555
|
+
isCustomElement) {
|
|
2556
|
+
let directiveToUse = V_MODEL_TEXT;
|
|
2557
|
+
let isInvalidType = false;
|
|
2558
|
+
if (tag === 'input' || isCustomElement) {
|
|
2559
|
+
const type = compilerCore.findProp(node, `type`);
|
|
2560
|
+
if (type) {
|
|
2561
|
+
if (type.type === 7 /* NodeTypes.DIRECTIVE */) {
|
|
2562
|
+
// :type="foo"
|
|
2563
|
+
directiveToUse = V_MODEL_DYNAMIC;
|
|
2564
|
+
}
|
|
2565
|
+
else if (type.value) {
|
|
2566
|
+
switch (type.value.content) {
|
|
2567
|
+
case 'radio':
|
|
2568
|
+
directiveToUse = V_MODEL_RADIO;
|
|
2569
|
+
break;
|
|
2570
|
+
case 'checkbox':
|
|
2571
|
+
directiveToUse = V_MODEL_CHECKBOX;
|
|
2572
|
+
break;
|
|
2573
|
+
case 'file':
|
|
2574
|
+
isInvalidType = true;
|
|
2575
|
+
context.onError(createDOMCompilerError(56 /* DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT */, dir.loc));
|
|
2576
|
+
break;
|
|
2577
|
+
default:
|
|
2578
|
+
// text type
|
|
2579
|
+
checkDuplicatedValue();
|
|
2580
|
+
break;
|
|
2581
|
+
}
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
else if (compilerCore.hasDynamicKeyVBind(node)) {
|
|
2585
|
+
// element has bindings with dynamic keys, which can possibly contain
|
|
2586
|
+
// "type".
|
|
2587
|
+
directiveToUse = V_MODEL_DYNAMIC;
|
|
2588
|
+
}
|
|
2589
|
+
else {
|
|
2590
|
+
// text type
|
|
2591
|
+
checkDuplicatedValue();
|
|
2592
|
+
}
|
|
2593
|
+
}
|
|
2594
|
+
else if (tag === 'select') {
|
|
2595
|
+
directiveToUse = V_MODEL_SELECT;
|
|
2596
|
+
}
|
|
2597
|
+
else {
|
|
2598
|
+
// textarea
|
|
2599
|
+
checkDuplicatedValue();
|
|
2600
|
+
}
|
|
2601
|
+
// inject runtime directive
|
|
2602
|
+
// by returning the helper symbol via needRuntime
|
|
2603
|
+
// the import will replaced a resolveDirective call.
|
|
2604
|
+
if (!isInvalidType) {
|
|
2605
|
+
baseResult.needRuntime = context.helper(directiveToUse);
|
|
2606
|
+
}
|
|
2607
|
+
}
|
|
2608
|
+
else {
|
|
2609
|
+
context.onError(createDOMCompilerError(54 /* DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT */, dir.loc));
|
|
2610
|
+
}
|
|
2611
|
+
// native vmodel doesn't need the `modelValue` props since they are also
|
|
2612
|
+
// passed to the runtime as `binding.value`. removing it reduces code size.
|
|
2613
|
+
baseResult.props = baseResult.props.filter(p => !(p.key.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
|
|
2614
|
+
p.key.content === 'modelValue'));
|
|
2615
|
+
return baseResult;
|
|
2616
2616
|
};
|
|
2617
2617
|
|
|
2618
|
-
const isEventOptionModifier = /*#__PURE__*/ shared.makeMap(`passive,once,capture`);
|
|
2619
|
-
const isNonKeyModifier = /*#__PURE__*/ shared.makeMap(
|
|
2620
|
-
// event propagation management
|
|
2621
|
-
`stop,prevent,self,` +
|
|
2622
|
-
// system modifiers + exact
|
|
2623
|
-
`ctrl,shift,alt,meta,exact,` +
|
|
2624
|
-
// mouse
|
|
2625
|
-
`middle`);
|
|
2626
|
-
// left & right could be mouse or key modifiers based on event type
|
|
2627
|
-
const maybeKeyModifier = /*#__PURE__*/ shared.makeMap('left,right');
|
|
2628
|
-
const isKeyboardEvent = /*#__PURE__*/ shared.makeMap(`onkeyup,onkeydown,onkeypress`, true);
|
|
2629
|
-
const resolveModifiers = (key, modifiers, context, loc) => {
|
|
2630
|
-
const keyModifiers = [];
|
|
2631
|
-
const nonKeyModifiers = [];
|
|
2632
|
-
const eventOptionModifiers = [];
|
|
2633
|
-
for (let i = 0; i < modifiers.length; i++) {
|
|
2634
|
-
const modifier = modifiers[i];
|
|
2635
|
-
if (modifier === 'native' &&
|
|
2636
|
-
compilerCore.checkCompatEnabled("COMPILER_V_ON_NATIVE" /* CompilerDeprecationTypes.COMPILER_V_ON_NATIVE */, context, loc)) {
|
|
2637
|
-
eventOptionModifiers.push(modifier);
|
|
2638
|
-
}
|
|
2639
|
-
else if (isEventOptionModifier(modifier)) {
|
|
2640
|
-
// eventOptionModifiers: modifiers for addEventListener() options,
|
|
2641
|
-
// e.g. .passive & .capture
|
|
2642
|
-
eventOptionModifiers.push(modifier);
|
|
2643
|
-
}
|
|
2644
|
-
else {
|
|
2645
|
-
// runtimeModifiers: modifiers that needs runtime guards
|
|
2646
|
-
if (maybeKeyModifier(modifier)) {
|
|
2647
|
-
if (compilerCore.isStaticExp(key)) {
|
|
2648
|
-
if (isKeyboardEvent(key.content)) {
|
|
2649
|
-
keyModifiers.push(modifier);
|
|
2650
|
-
}
|
|
2651
|
-
else {
|
|
2652
|
-
nonKeyModifiers.push(modifier);
|
|
2653
|
-
}
|
|
2654
|
-
}
|
|
2655
|
-
else {
|
|
2656
|
-
keyModifiers.push(modifier);
|
|
2657
|
-
nonKeyModifiers.push(modifier);
|
|
2658
|
-
}
|
|
2659
|
-
}
|
|
2660
|
-
else {
|
|
2661
|
-
if (isNonKeyModifier(modifier)) {
|
|
2662
|
-
nonKeyModifiers.push(modifier);
|
|
2663
|
-
}
|
|
2664
|
-
else {
|
|
2665
|
-
keyModifiers.push(modifier);
|
|
2666
|
-
}
|
|
2667
|
-
}
|
|
2668
|
-
}
|
|
2669
|
-
}
|
|
2670
|
-
return {
|
|
2671
|
-
keyModifiers,
|
|
2672
|
-
nonKeyModifiers,
|
|
2673
|
-
eventOptionModifiers
|
|
2674
|
-
};
|
|
2675
|
-
};
|
|
2676
|
-
const transformClick = (key, event) => {
|
|
2677
|
-
const isStaticClick = compilerCore.isStaticExp(key) && key.content.toLowerCase() === 'onclick';
|
|
2678
|
-
return isStaticClick
|
|
2679
|
-
? compilerCore.createSimpleExpression(event, true)
|
|
2680
|
-
: key.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */
|
|
2681
|
-
? compilerCore.createCompoundExpression([
|
|
2682
|
-
`(`,
|
|
2683
|
-
key,
|
|
2684
|
-
`) === "onClick" ? "${event}" : (`,
|
|
2685
|
-
key,
|
|
2686
|
-
`)`
|
|
2687
|
-
])
|
|
2688
|
-
: key;
|
|
2689
|
-
};
|
|
2690
|
-
const transformOn = (dir, node, context) => {
|
|
2691
|
-
return compilerCore.transformOn(dir, node, context, baseResult => {
|
|
2692
|
-
const { modifiers } = dir;
|
|
2693
|
-
if (!modifiers.length)
|
|
2694
|
-
return baseResult;
|
|
2695
|
-
let { key, value: handlerExp } = baseResult.props[0];
|
|
2696
|
-
const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = resolveModifiers(key, modifiers, context, dir.loc);
|
|
2697
|
-
// normalize click.right and click.middle since they don't actually fire
|
|
2698
|
-
if (nonKeyModifiers.includes('right')) {
|
|
2699
|
-
key = transformClick(key, `onContextmenu`);
|
|
2700
|
-
}
|
|
2701
|
-
if (nonKeyModifiers.includes('middle')) {
|
|
2702
|
-
key = transformClick(key, `onMouseup`);
|
|
2703
|
-
}
|
|
2704
|
-
if (nonKeyModifiers.length) {
|
|
2705
|
-
handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [
|
|
2706
|
-
handlerExp,
|
|
2707
|
-
JSON.stringify(nonKeyModifiers)
|
|
2708
|
-
]);
|
|
2709
|
-
}
|
|
2710
|
-
if (keyModifiers.length &&
|
|
2711
|
-
// if event name is dynamic, always wrap with keys guard
|
|
2712
|
-
(!compilerCore.isStaticExp(key) || isKeyboardEvent(key.content))) {
|
|
2713
|
-
handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_KEYS), [
|
|
2714
|
-
handlerExp,
|
|
2715
|
-
JSON.stringify(keyModifiers)
|
|
2716
|
-
]);
|
|
2717
|
-
}
|
|
2718
|
-
if (eventOptionModifiers.length) {
|
|
2719
|
-
const modifierPostfix = eventOptionModifiers.map(shared.capitalize).join('');
|
|
2720
|
-
key = compilerCore.isStaticExp(key)
|
|
2721
|
-
? compilerCore.createSimpleExpression(`${key.content}${modifierPostfix}`, true)
|
|
2722
|
-
: compilerCore.createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`]);
|
|
2723
|
-
}
|
|
2724
|
-
return {
|
|
2725
|
-
props: [compilerCore.createObjectProperty(key, handlerExp)]
|
|
2726
|
-
};
|
|
2727
|
-
});
|
|
2618
|
+
const isEventOptionModifier = /*#__PURE__*/ shared.makeMap(`passive,once,capture`);
|
|
2619
|
+
const isNonKeyModifier = /*#__PURE__*/ shared.makeMap(
|
|
2620
|
+
// event propagation management
|
|
2621
|
+
`stop,prevent,self,` +
|
|
2622
|
+
// system modifiers + exact
|
|
2623
|
+
`ctrl,shift,alt,meta,exact,` +
|
|
2624
|
+
// mouse
|
|
2625
|
+
`middle`);
|
|
2626
|
+
// left & right could be mouse or key modifiers based on event type
|
|
2627
|
+
const maybeKeyModifier = /*#__PURE__*/ shared.makeMap('left,right');
|
|
2628
|
+
const isKeyboardEvent = /*#__PURE__*/ shared.makeMap(`onkeyup,onkeydown,onkeypress`, true);
|
|
2629
|
+
const resolveModifiers = (key, modifiers, context, loc) => {
|
|
2630
|
+
const keyModifiers = [];
|
|
2631
|
+
const nonKeyModifiers = [];
|
|
2632
|
+
const eventOptionModifiers = [];
|
|
2633
|
+
for (let i = 0; i < modifiers.length; i++) {
|
|
2634
|
+
const modifier = modifiers[i];
|
|
2635
|
+
if (modifier === 'native' &&
|
|
2636
|
+
compilerCore.checkCompatEnabled("COMPILER_V_ON_NATIVE" /* CompilerDeprecationTypes.COMPILER_V_ON_NATIVE */, context, loc)) {
|
|
2637
|
+
eventOptionModifiers.push(modifier);
|
|
2638
|
+
}
|
|
2639
|
+
else if (isEventOptionModifier(modifier)) {
|
|
2640
|
+
// eventOptionModifiers: modifiers for addEventListener() options,
|
|
2641
|
+
// e.g. .passive & .capture
|
|
2642
|
+
eventOptionModifiers.push(modifier);
|
|
2643
|
+
}
|
|
2644
|
+
else {
|
|
2645
|
+
// runtimeModifiers: modifiers that needs runtime guards
|
|
2646
|
+
if (maybeKeyModifier(modifier)) {
|
|
2647
|
+
if (compilerCore.isStaticExp(key)) {
|
|
2648
|
+
if (isKeyboardEvent(key.content)) {
|
|
2649
|
+
keyModifiers.push(modifier);
|
|
2650
|
+
}
|
|
2651
|
+
else {
|
|
2652
|
+
nonKeyModifiers.push(modifier);
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
else {
|
|
2656
|
+
keyModifiers.push(modifier);
|
|
2657
|
+
nonKeyModifiers.push(modifier);
|
|
2658
|
+
}
|
|
2659
|
+
}
|
|
2660
|
+
else {
|
|
2661
|
+
if (isNonKeyModifier(modifier)) {
|
|
2662
|
+
nonKeyModifiers.push(modifier);
|
|
2663
|
+
}
|
|
2664
|
+
else {
|
|
2665
|
+
keyModifiers.push(modifier);
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
return {
|
|
2671
|
+
keyModifiers,
|
|
2672
|
+
nonKeyModifiers,
|
|
2673
|
+
eventOptionModifiers
|
|
2674
|
+
};
|
|
2675
|
+
};
|
|
2676
|
+
const transformClick = (key, event) => {
|
|
2677
|
+
const isStaticClick = compilerCore.isStaticExp(key) && key.content.toLowerCase() === 'onclick';
|
|
2678
|
+
return isStaticClick
|
|
2679
|
+
? compilerCore.createSimpleExpression(event, true)
|
|
2680
|
+
: key.type !== 4 /* NodeTypes.SIMPLE_EXPRESSION */
|
|
2681
|
+
? compilerCore.createCompoundExpression([
|
|
2682
|
+
`(`,
|
|
2683
|
+
key,
|
|
2684
|
+
`) === "onClick" ? "${event}" : (`,
|
|
2685
|
+
key,
|
|
2686
|
+
`)`
|
|
2687
|
+
])
|
|
2688
|
+
: key;
|
|
2689
|
+
};
|
|
2690
|
+
const transformOn = (dir, node, context) => {
|
|
2691
|
+
return compilerCore.transformOn(dir, node, context, baseResult => {
|
|
2692
|
+
const { modifiers } = dir;
|
|
2693
|
+
if (!modifiers.length)
|
|
2694
|
+
return baseResult;
|
|
2695
|
+
let { key, value: handlerExp } = baseResult.props[0];
|
|
2696
|
+
const { keyModifiers, nonKeyModifiers, eventOptionModifiers } = resolveModifiers(key, modifiers, context, dir.loc);
|
|
2697
|
+
// normalize click.right and click.middle since they don't actually fire
|
|
2698
|
+
if (nonKeyModifiers.includes('right')) {
|
|
2699
|
+
key = transformClick(key, `onContextmenu`);
|
|
2700
|
+
}
|
|
2701
|
+
if (nonKeyModifiers.includes('middle')) {
|
|
2702
|
+
key = transformClick(key, `onMouseup`);
|
|
2703
|
+
}
|
|
2704
|
+
if (nonKeyModifiers.length) {
|
|
2705
|
+
handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [
|
|
2706
|
+
handlerExp,
|
|
2707
|
+
JSON.stringify(nonKeyModifiers)
|
|
2708
|
+
]);
|
|
2709
|
+
}
|
|
2710
|
+
if (keyModifiers.length &&
|
|
2711
|
+
// if event name is dynamic, always wrap with keys guard
|
|
2712
|
+
(!compilerCore.isStaticExp(key) || isKeyboardEvent(key.content))) {
|
|
2713
|
+
handlerExp = compilerCore.createCallExpression(context.helper(V_ON_WITH_KEYS), [
|
|
2714
|
+
handlerExp,
|
|
2715
|
+
JSON.stringify(keyModifiers)
|
|
2716
|
+
]);
|
|
2717
|
+
}
|
|
2718
|
+
if (eventOptionModifiers.length) {
|
|
2719
|
+
const modifierPostfix = eventOptionModifiers.map(shared.capitalize).join('');
|
|
2720
|
+
key = compilerCore.isStaticExp(key)
|
|
2721
|
+
? compilerCore.createSimpleExpression(`${key.content}${modifierPostfix}`, true)
|
|
2722
|
+
: compilerCore.createCompoundExpression([`(`, key, `) + "${modifierPostfix}"`]);
|
|
2723
|
+
}
|
|
2724
|
+
return {
|
|
2725
|
+
props: [compilerCore.createObjectProperty(key, handlerExp)]
|
|
2726
|
+
};
|
|
2727
|
+
});
|
|
2728
2728
|
};
|
|
2729
2729
|
|
|
2730
|
-
const transformShow = (dir, node, context) => {
|
|
2731
|
-
const { exp, loc } = dir;
|
|
2732
|
-
if (!exp) {
|
|
2733
|
-
context.onError(createDOMCompilerError(58 /* DOMErrorCodes.X_V_SHOW_NO_EXPRESSION */, loc));
|
|
2734
|
-
}
|
|
2735
|
-
return {
|
|
2736
|
-
props: [],
|
|
2737
|
-
needRuntime: context.helper(V_SHOW)
|
|
2738
|
-
};
|
|
2730
|
+
const transformShow = (dir, node, context) => {
|
|
2731
|
+
const { exp, loc } = dir;
|
|
2732
|
+
if (!exp) {
|
|
2733
|
+
context.onError(createDOMCompilerError(58 /* DOMErrorCodes.X_V_SHOW_NO_EXPRESSION */, loc));
|
|
2734
|
+
}
|
|
2735
|
+
return {
|
|
2736
|
+
props: [],
|
|
2737
|
+
needRuntime: context.helper(V_SHOW)
|
|
2738
|
+
};
|
|
2739
2739
|
};
|
|
2740
2740
|
|
|
2741
|
-
const transformTransition = (node, context) => {
|
|
2742
|
-
if (node.type === 1 /* NodeTypes.ELEMENT */ &&
|
|
2743
|
-
node.tagType === 1 /* ElementTypes.COMPONENT */) {
|
|
2744
|
-
const component = context.isBuiltInComponent(node.tag);
|
|
2745
|
-
if (component === TRANSITION) {
|
|
2746
|
-
return () => {
|
|
2747
|
-
if (!node.children.length) {
|
|
2748
|
-
return;
|
|
2749
|
-
}
|
|
2750
|
-
// warn multiple transition children
|
|
2751
|
-
if (hasMultipleChildren(node)) {
|
|
2752
|
-
context.onError(createDOMCompilerError(59 /* DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN */, {
|
|
2753
|
-
start: node.children[0].loc.start,
|
|
2754
|
-
end: node.children[node.children.length - 1].loc.end,
|
|
2755
|
-
source: ''
|
|
2756
|
-
}));
|
|
2757
|
-
}
|
|
2758
|
-
// check if it's s single child w/ v-show
|
|
2759
|
-
// if yes, inject "persisted: true" to the transition props
|
|
2760
|
-
const child = node.children[0];
|
|
2761
|
-
if (child.type === 1 /* NodeTypes.ELEMENT */) {
|
|
2762
|
-
for (const p of child.props) {
|
|
2763
|
-
if (p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'show') {
|
|
2764
|
-
node.props.push({
|
|
2765
|
-
type: 6 /* NodeTypes.ATTRIBUTE */,
|
|
2766
|
-
name: 'persisted',
|
|
2767
|
-
value: undefined,
|
|
2768
|
-
loc: node.loc
|
|
2769
|
-
});
|
|
2770
|
-
}
|
|
2771
|
-
}
|
|
2772
|
-
}
|
|
2773
|
-
};
|
|
2774
|
-
}
|
|
2775
|
-
}
|
|
2776
|
-
};
|
|
2777
|
-
function hasMultipleChildren(node) {
|
|
2778
|
-
// #1352 filter out potential comment nodes.
|
|
2779
|
-
const children = (node.children = node.children.filter(c => c.type !== 3 /* NodeTypes.COMMENT */ &&
|
|
2780
|
-
!(c.type === 2 /* NodeTypes.TEXT */ && !c.content.trim())));
|
|
2781
|
-
const child = children[0];
|
|
2782
|
-
return (children.length !== 1 ||
|
|
2783
|
-
child.type === 11 /* NodeTypes.FOR */ ||
|
|
2784
|
-
(child.type === 9 /* NodeTypes.IF */ && child.branches.some(hasMultipleChildren)));
|
|
2741
|
+
const transformTransition = (node, context) => {
|
|
2742
|
+
if (node.type === 1 /* NodeTypes.ELEMENT */ &&
|
|
2743
|
+
node.tagType === 1 /* ElementTypes.COMPONENT */) {
|
|
2744
|
+
const component = context.isBuiltInComponent(node.tag);
|
|
2745
|
+
if (component === TRANSITION) {
|
|
2746
|
+
return () => {
|
|
2747
|
+
if (!node.children.length) {
|
|
2748
|
+
return;
|
|
2749
|
+
}
|
|
2750
|
+
// warn multiple transition children
|
|
2751
|
+
if (hasMultipleChildren(node)) {
|
|
2752
|
+
context.onError(createDOMCompilerError(59 /* DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN */, {
|
|
2753
|
+
start: node.children[0].loc.start,
|
|
2754
|
+
end: node.children[node.children.length - 1].loc.end,
|
|
2755
|
+
source: ''
|
|
2756
|
+
}));
|
|
2757
|
+
}
|
|
2758
|
+
// check if it's s single child w/ v-show
|
|
2759
|
+
// if yes, inject "persisted: true" to the transition props
|
|
2760
|
+
const child = node.children[0];
|
|
2761
|
+
if (child.type === 1 /* NodeTypes.ELEMENT */) {
|
|
2762
|
+
for (const p of child.props) {
|
|
2763
|
+
if (p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'show') {
|
|
2764
|
+
node.props.push({
|
|
2765
|
+
type: 6 /* NodeTypes.ATTRIBUTE */,
|
|
2766
|
+
name: 'persisted',
|
|
2767
|
+
value: undefined,
|
|
2768
|
+
loc: node.loc
|
|
2769
|
+
});
|
|
2770
|
+
}
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2773
|
+
};
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
};
|
|
2777
|
+
function hasMultipleChildren(node) {
|
|
2778
|
+
// #1352 filter out potential comment nodes.
|
|
2779
|
+
const children = (node.children = node.children.filter(c => c.type !== 3 /* NodeTypes.COMMENT */ &&
|
|
2780
|
+
!(c.type === 2 /* NodeTypes.TEXT */ && !c.content.trim())));
|
|
2781
|
+
const child = children[0];
|
|
2782
|
+
return (children.length !== 1 ||
|
|
2783
|
+
child.type === 11 /* NodeTypes.FOR */ ||
|
|
2784
|
+
(child.type === 9 /* NodeTypes.IF */ && child.branches.some(hasMultipleChildren)));
|
|
2785
2785
|
}
|
|
2786
2786
|
|
|
2787
|
-
/**
|
|
2788
|
-
* This module is Node-only.
|
|
2789
|
-
*/
|
|
2790
|
-
/**
|
|
2791
|
-
* Regex for replacing placeholders for embedded constant variables
|
|
2792
|
-
* (e.g. import URL string constants generated by compiler-sfc)
|
|
2793
|
-
*/
|
|
2794
|
-
const expReplaceRE = /__VUE_EXP_START__(.*?)__VUE_EXP_END__/g;
|
|
2795
|
-
/**
|
|
2796
|
-
* Turn eligible hoisted static trees into stringified static nodes, e.g.
|
|
2797
|
-
*
|
|
2798
|
-
* ```js
|
|
2799
|
-
* const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
|
|
2800
|
-
* ```
|
|
2801
|
-
*
|
|
2802
|
-
* A single static vnode can contain stringified content for **multiple**
|
|
2803
|
-
* consecutive nodes (element and plain text), called a "chunk".
|
|
2804
|
-
* `@vue/runtime-dom` will create the content via innerHTML in a hidden
|
|
2805
|
-
* container element and insert all the nodes in place. The call must also
|
|
2806
|
-
* provide the number of nodes contained in the chunk so that during hydration
|
|
2807
|
-
* we can know how many nodes the static vnode should adopt.
|
|
2808
|
-
*
|
|
2809
|
-
* The optimization scans a children list that contains hoisted nodes, and
|
|
2810
|
-
* tries to find the largest chunk of consecutive hoisted nodes before running
|
|
2811
|
-
* into a non-hoisted node or the end of the list. A chunk is then converted
|
|
2812
|
-
* into a single static vnode and replaces the hoisted expression of the first
|
|
2813
|
-
* node in the chunk. Other nodes in the chunk are considered "merged" and
|
|
2814
|
-
* therefore removed from both the hoist list and the children array.
|
|
2815
|
-
*
|
|
2816
|
-
* This optimization is only performed in Node.js.
|
|
2817
|
-
*/
|
|
2818
|
-
const stringifyStatic = (children, context, parent) => {
|
|
2819
|
-
// bail stringification for slot content
|
|
2820
|
-
if (context.scopes.vSlot > 0) {
|
|
2821
|
-
return;
|
|
2822
|
-
}
|
|
2823
|
-
let nc = 0; // current node count
|
|
2824
|
-
let ec = 0; // current element with binding count
|
|
2825
|
-
const currentChunk = [];
|
|
2826
|
-
const stringifyCurrentChunk = (currentIndex) => {
|
|
2827
|
-
if (nc >= 20 /* StringifyThresholds.NODE_COUNT */ ||
|
|
2828
|
-
ec >= 5 /* StringifyThresholds.ELEMENT_WITH_BINDING_COUNT */) {
|
|
2829
|
-
// combine all currently eligible nodes into a single static vnode call
|
|
2830
|
-
const staticCall = compilerCore.createCallExpression(context.helper(compilerCore.CREATE_STATIC), [
|
|
2831
|
-
JSON.stringify(currentChunk.map(node => stringifyNode(node, context)).join('')).replace(expReplaceRE, `" + $1 + "`),
|
|
2832
|
-
// the 2nd argument indicates the number of DOM nodes this static vnode
|
|
2833
|
-
// will insert / hydrate
|
|
2834
|
-
String(currentChunk.length)
|
|
2835
|
-
]);
|
|
2836
|
-
// replace the first node's hoisted expression with the static vnode call
|
|
2837
|
-
replaceHoist(currentChunk[0], staticCall, context);
|
|
2838
|
-
if (currentChunk.length > 1) {
|
|
2839
|
-
for (let i = 1; i < currentChunk.length; i++) {
|
|
2840
|
-
// for the merged nodes, set their hoisted expression to null
|
|
2841
|
-
replaceHoist(currentChunk[i], null, context);
|
|
2842
|
-
}
|
|
2843
|
-
// also remove merged nodes from children
|
|
2844
|
-
const deleteCount = currentChunk.length - 1;
|
|
2845
|
-
children.splice(currentIndex - currentChunk.length + 1, deleteCount);
|
|
2846
|
-
return deleteCount;
|
|
2847
|
-
}
|
|
2848
|
-
}
|
|
2849
|
-
return 0;
|
|
2850
|
-
};
|
|
2851
|
-
let i = 0;
|
|
2852
|
-
for (; i < children.length; i++) {
|
|
2853
|
-
const child = children[i];
|
|
2854
|
-
const hoisted = getHoistedNode(child);
|
|
2855
|
-
if (hoisted) {
|
|
2856
|
-
// presence of hoisted means child must be a stringifiable node
|
|
2857
|
-
const node = child;
|
|
2858
|
-
const result = analyzeNode(node);
|
|
2859
|
-
if (result) {
|
|
2860
|
-
// node is stringifiable, record state
|
|
2861
|
-
nc += result[0];
|
|
2862
|
-
ec += result[1];
|
|
2863
|
-
currentChunk.push(node);
|
|
2864
|
-
continue;
|
|
2865
|
-
}
|
|
2866
|
-
}
|
|
2867
|
-
// we only reach here if we ran into a node that is not stringifiable
|
|
2868
|
-
// check if currently analyzed nodes meet criteria for stringification.
|
|
2869
|
-
// adjust iteration index
|
|
2870
|
-
i -= stringifyCurrentChunk(i);
|
|
2871
|
-
// reset state
|
|
2872
|
-
nc = 0;
|
|
2873
|
-
ec = 0;
|
|
2874
|
-
currentChunk.length = 0;
|
|
2875
|
-
}
|
|
2876
|
-
// in case the last node was also stringifiable
|
|
2877
|
-
stringifyCurrentChunk(i);
|
|
2878
|
-
};
|
|
2879
|
-
const getHoistedNode = (node) => ((node.type === 1 /* NodeTypes.ELEMENT */ && node.tagType === 0 /* ElementTypes.ELEMENT */) ||
|
|
2880
|
-
node.type == 12 /* NodeTypes.TEXT_CALL */) &&
|
|
2881
|
-
node.codegenNode &&
|
|
2882
|
-
node.codegenNode.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
|
|
2883
|
-
node.codegenNode.hoisted;
|
|
2884
|
-
const dataAriaRE = /^(data|aria)-/;
|
|
2885
|
-
const isStringifiableAttr = (name, ns) => {
|
|
2886
|
-
return ((ns === 0 /* DOMNamespaces.HTML */
|
|
2887
|
-
? shared.isKnownHtmlAttr(name)
|
|
2888
|
-
: ns === 1 /* DOMNamespaces.SVG */
|
|
2889
|
-
? shared.isKnownSvgAttr(name)
|
|
2890
|
-
: false) || dataAriaRE.test(name));
|
|
2891
|
-
};
|
|
2892
|
-
const replaceHoist = (node, replacement, context) => {
|
|
2893
|
-
const hoistToReplace = node.codegenNode.hoisted;
|
|
2894
|
-
context.hoists[context.hoists.indexOf(hoistToReplace)] = replacement;
|
|
2895
|
-
};
|
|
2896
|
-
const isNonStringifiable = /*#__PURE__*/ shared.makeMap(`caption,thead,tr,th,tbody,td,tfoot,colgroup,col`);
|
|
2897
|
-
/**
|
|
2898
|
-
* for a hoisted node, analyze it and return:
|
|
2899
|
-
* - false: bailed (contains non-stringifiable props or runtime constant)
|
|
2900
|
-
* - [nc, ec] where
|
|
2901
|
-
* - nc is the number of nodes inside
|
|
2902
|
-
* - ec is the number of element with bindings inside
|
|
2903
|
-
*/
|
|
2904
|
-
function analyzeNode(node) {
|
|
2905
|
-
if (node.type === 1 /* NodeTypes.ELEMENT */ && isNonStringifiable(node.tag)) {
|
|
2906
|
-
return false;
|
|
2907
|
-
}
|
|
2908
|
-
if (node.type === 12 /* NodeTypes.TEXT_CALL */) {
|
|
2909
|
-
return [1, 0];
|
|
2910
|
-
}
|
|
2911
|
-
let nc = 1; // node count
|
|
2912
|
-
let ec = node.props.length > 0 ? 1 : 0; // element w/ binding count
|
|
2913
|
-
let bailed = false;
|
|
2914
|
-
const bail = () => {
|
|
2915
|
-
bailed = true;
|
|
2916
|
-
return false;
|
|
2917
|
-
};
|
|
2918
|
-
// TODO: check for cases where using innerHTML will result in different
|
|
2919
|
-
// output compared to imperative node insertions.
|
|
2920
|
-
// probably only need to check for most common case
|
|
2921
|
-
// i.e. non-phrasing-content tags inside `<p>`
|
|
2922
|
-
function walk(node) {
|
|
2923
|
-
for (let i = 0; i < node.props.length; i++) {
|
|
2924
|
-
const p = node.props[i];
|
|
2925
|
-
// bail on non-attr bindings
|
|
2926
|
-
if (p.type === 6 /* NodeTypes.ATTRIBUTE */ &&
|
|
2927
|
-
!isStringifiableAttr(p.name, node.ns)) {
|
|
2928
|
-
return bail();
|
|
2929
|
-
}
|
|
2930
|
-
if (p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'bind') {
|
|
2931
|
-
// bail on non-attr bindings
|
|
2932
|
-
if (p.arg &&
|
|
2933
|
-
(p.arg.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */ ||
|
|
2934
|
-
(p.arg.isStatic && !isStringifiableAttr(p.arg.content, node.ns)))) {
|
|
2935
|
-
return bail();
|
|
2936
|
-
}
|
|
2937
|
-
if (p.exp &&
|
|
2938
|
-
(p.exp.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */ ||
|
|
2939
|
-
p.exp.constType < 3 /* ConstantTypes.CAN_STRINGIFY */)) {
|
|
2940
|
-
return bail();
|
|
2941
|
-
}
|
|
2942
|
-
}
|
|
2943
|
-
}
|
|
2944
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
2945
|
-
nc++;
|
|
2946
|
-
const child = node.children[i];
|
|
2947
|
-
if (child.type === 1 /* NodeTypes.ELEMENT */) {
|
|
2948
|
-
if (child.props.length > 0) {
|
|
2949
|
-
ec++;
|
|
2950
|
-
}
|
|
2951
|
-
walk(child);
|
|
2952
|
-
if (bailed) {
|
|
2953
|
-
return false;
|
|
2954
|
-
}
|
|
2955
|
-
}
|
|
2956
|
-
}
|
|
2957
|
-
return true;
|
|
2958
|
-
}
|
|
2959
|
-
return walk(node) ? [nc, ec] : false;
|
|
2960
|
-
}
|
|
2961
|
-
function stringifyNode(node, context) {
|
|
2962
|
-
if (shared.isString(node)) {
|
|
2963
|
-
return node;
|
|
2964
|
-
}
|
|
2965
|
-
if (shared.isSymbol(node)) {
|
|
2966
|
-
return ``;
|
|
2967
|
-
}
|
|
2968
|
-
switch (node.type) {
|
|
2969
|
-
case 1 /* NodeTypes.ELEMENT */:
|
|
2970
|
-
return stringifyElement(node, context);
|
|
2971
|
-
case 2 /* NodeTypes.TEXT */:
|
|
2972
|
-
return shared.escapeHtml(node.content);
|
|
2973
|
-
case 3 /* NodeTypes.COMMENT */:
|
|
2974
|
-
return `<!--${shared.escapeHtml(node.content)}-->`;
|
|
2975
|
-
case 5 /* NodeTypes.INTERPOLATION */:
|
|
2976
|
-
return shared.escapeHtml(shared.toDisplayString(evaluateConstant(node.content)));
|
|
2977
|
-
case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
|
|
2978
|
-
return shared.escapeHtml(evaluateConstant(node));
|
|
2979
|
-
case 12 /* NodeTypes.TEXT_CALL */:
|
|
2980
|
-
return stringifyNode(node.content, context);
|
|
2981
|
-
default:
|
|
2982
|
-
// static trees will not contain if/for nodes
|
|
2983
|
-
return '';
|
|
2984
|
-
}
|
|
2985
|
-
}
|
|
2986
|
-
function stringifyElement(node, context) {
|
|
2987
|
-
let res = `<${node.tag}`;
|
|
2988
|
-
let innerHTML = '';
|
|
2989
|
-
for (let i = 0; i < node.props.length; i++) {
|
|
2990
|
-
const p = node.props[i];
|
|
2991
|
-
if (p.type === 6 /* NodeTypes.ATTRIBUTE */) {
|
|
2992
|
-
res += ` ${p.name}`;
|
|
2993
|
-
if (p.value) {
|
|
2994
|
-
res += `="${shared.escapeHtml(p.value.content)}"`;
|
|
2995
|
-
}
|
|
2996
|
-
}
|
|
2997
|
-
else if (p.type === 7 /* NodeTypes.DIRECTIVE */) {
|
|
2998
|
-
if (p.name === 'bind') {
|
|
2999
|
-
const exp = p.exp;
|
|
3000
|
-
if (exp.content[0] === '_') {
|
|
3001
|
-
// internally generated string constant references
|
|
3002
|
-
// e.g. imported URL strings via compiler-sfc transformAssetUrl plugin
|
|
3003
|
-
res += ` ${p.arg.content}="__VUE_EXP_START__${exp.content}__VUE_EXP_END__"`;
|
|
3004
|
-
continue;
|
|
3005
|
-
}
|
|
3006
|
-
// #6568
|
|
3007
|
-
if (shared.isBooleanAttr(p.arg.content) &&
|
|
3008
|
-
exp.content === 'false') {
|
|
3009
|
-
continue;
|
|
3010
|
-
}
|
|
3011
|
-
// constant v-bind, e.g. :foo="1"
|
|
3012
|
-
let evaluated = evaluateConstant(exp);
|
|
3013
|
-
if (evaluated != null) {
|
|
3014
|
-
const arg = p.arg && p.arg.content;
|
|
3015
|
-
if (arg === 'class') {
|
|
3016
|
-
evaluated = shared.normalizeClass(evaluated);
|
|
3017
|
-
}
|
|
3018
|
-
else if (arg === 'style') {
|
|
3019
|
-
evaluated = shared.stringifyStyle(shared.normalizeStyle(evaluated));
|
|
3020
|
-
}
|
|
3021
|
-
res += ` ${p.arg.content}="${shared.escapeHtml(evaluated)}"`;
|
|
3022
|
-
}
|
|
3023
|
-
}
|
|
3024
|
-
else if (p.name === 'html') {
|
|
3025
|
-
// #5439 v-html with constant value
|
|
3026
|
-
// not sure why would anyone do this but it can happen
|
|
3027
|
-
innerHTML = evaluateConstant(p.exp);
|
|
3028
|
-
}
|
|
3029
|
-
else if (p.name === 'text') {
|
|
3030
|
-
innerHTML = shared.escapeHtml(shared.toDisplayString(evaluateConstant(p.exp)));
|
|
3031
|
-
}
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
if (context.scopeId) {
|
|
3035
|
-
res += ` ${context.scopeId}`;
|
|
3036
|
-
}
|
|
3037
|
-
res += `>`;
|
|
3038
|
-
if (innerHTML) {
|
|
3039
|
-
res += innerHTML;
|
|
3040
|
-
}
|
|
3041
|
-
else {
|
|
3042
|
-
for (let i = 0; i < node.children.length; i++) {
|
|
3043
|
-
res += stringifyNode(node.children[i], context);
|
|
3044
|
-
}
|
|
3045
|
-
}
|
|
3046
|
-
if (!shared.isVoidTag(node.tag)) {
|
|
3047
|
-
res += `</${node.tag}>`;
|
|
3048
|
-
}
|
|
3049
|
-
return res;
|
|
3050
|
-
}
|
|
3051
|
-
// __UNSAFE__
|
|
3052
|
-
// Reason: eval.
|
|
3053
|
-
// It's technically safe to eval because only constant expressions are possible
|
|
3054
|
-
// here, e.g. `{{ 1 }}` or `{{ 'foo' }}`
|
|
3055
|
-
// in addition, constant exps bail on presence of parens so you can't even
|
|
3056
|
-
// run JSFuck in here. But we mark it unsafe for security review purposes.
|
|
3057
|
-
// (see compiler-core/src/transforms/transformExpression)
|
|
3058
|
-
function evaluateConstant(exp) {
|
|
3059
|
-
if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
|
|
3060
|
-
return new Function(`return ${exp.content}`)();
|
|
3061
|
-
}
|
|
3062
|
-
else {
|
|
3063
|
-
// compound
|
|
3064
|
-
let res = ``;
|
|
3065
|
-
exp.children.forEach(c => {
|
|
3066
|
-
if (shared.isString(c) || shared.isSymbol(c)) {
|
|
3067
|
-
return;
|
|
3068
|
-
}
|
|
3069
|
-
if (c.type === 2 /* NodeTypes.TEXT */) {
|
|
3070
|
-
res += c.content;
|
|
3071
|
-
}
|
|
3072
|
-
else if (c.type === 5 /* NodeTypes.INTERPOLATION */) {
|
|
3073
|
-
res += shared.toDisplayString(evaluateConstant(c.content));
|
|
3074
|
-
}
|
|
3075
|
-
else {
|
|
3076
|
-
res += evaluateConstant(c);
|
|
3077
|
-
}
|
|
3078
|
-
});
|
|
3079
|
-
return res;
|
|
3080
|
-
}
|
|
2787
|
+
/**
|
|
2788
|
+
* This module is Node-only.
|
|
2789
|
+
*/
|
|
2790
|
+
/**
|
|
2791
|
+
* Regex for replacing placeholders for embedded constant variables
|
|
2792
|
+
* (e.g. import URL string constants generated by compiler-sfc)
|
|
2793
|
+
*/
|
|
2794
|
+
const expReplaceRE = /__VUE_EXP_START__(.*?)__VUE_EXP_END__/g;
|
|
2795
|
+
/**
|
|
2796
|
+
* Turn eligible hoisted static trees into stringified static nodes, e.g.
|
|
2797
|
+
*
|
|
2798
|
+
* ```js
|
|
2799
|
+
* const _hoisted_1 = createStaticVNode(`<div class="foo">bar</div>`)
|
|
2800
|
+
* ```
|
|
2801
|
+
*
|
|
2802
|
+
* A single static vnode can contain stringified content for **multiple**
|
|
2803
|
+
* consecutive nodes (element and plain text), called a "chunk".
|
|
2804
|
+
* `@vue/runtime-dom` will create the content via innerHTML in a hidden
|
|
2805
|
+
* container element and insert all the nodes in place. The call must also
|
|
2806
|
+
* provide the number of nodes contained in the chunk so that during hydration
|
|
2807
|
+
* we can know how many nodes the static vnode should adopt.
|
|
2808
|
+
*
|
|
2809
|
+
* The optimization scans a children list that contains hoisted nodes, and
|
|
2810
|
+
* tries to find the largest chunk of consecutive hoisted nodes before running
|
|
2811
|
+
* into a non-hoisted node or the end of the list. A chunk is then converted
|
|
2812
|
+
* into a single static vnode and replaces the hoisted expression of the first
|
|
2813
|
+
* node in the chunk. Other nodes in the chunk are considered "merged" and
|
|
2814
|
+
* therefore removed from both the hoist list and the children array.
|
|
2815
|
+
*
|
|
2816
|
+
* This optimization is only performed in Node.js.
|
|
2817
|
+
*/
|
|
2818
|
+
const stringifyStatic = (children, context, parent) => {
|
|
2819
|
+
// bail stringification for slot content
|
|
2820
|
+
if (context.scopes.vSlot > 0) {
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2823
|
+
let nc = 0; // current node count
|
|
2824
|
+
let ec = 0; // current element with binding count
|
|
2825
|
+
const currentChunk = [];
|
|
2826
|
+
const stringifyCurrentChunk = (currentIndex) => {
|
|
2827
|
+
if (nc >= 20 /* StringifyThresholds.NODE_COUNT */ ||
|
|
2828
|
+
ec >= 5 /* StringifyThresholds.ELEMENT_WITH_BINDING_COUNT */) {
|
|
2829
|
+
// combine all currently eligible nodes into a single static vnode call
|
|
2830
|
+
const staticCall = compilerCore.createCallExpression(context.helper(compilerCore.CREATE_STATIC), [
|
|
2831
|
+
JSON.stringify(currentChunk.map(node => stringifyNode(node, context)).join('')).replace(expReplaceRE, `" + $1 + "`),
|
|
2832
|
+
// the 2nd argument indicates the number of DOM nodes this static vnode
|
|
2833
|
+
// will insert / hydrate
|
|
2834
|
+
String(currentChunk.length)
|
|
2835
|
+
]);
|
|
2836
|
+
// replace the first node's hoisted expression with the static vnode call
|
|
2837
|
+
replaceHoist(currentChunk[0], staticCall, context);
|
|
2838
|
+
if (currentChunk.length > 1) {
|
|
2839
|
+
for (let i = 1; i < currentChunk.length; i++) {
|
|
2840
|
+
// for the merged nodes, set their hoisted expression to null
|
|
2841
|
+
replaceHoist(currentChunk[i], null, context);
|
|
2842
|
+
}
|
|
2843
|
+
// also remove merged nodes from children
|
|
2844
|
+
const deleteCount = currentChunk.length - 1;
|
|
2845
|
+
children.splice(currentIndex - currentChunk.length + 1, deleteCount);
|
|
2846
|
+
return deleteCount;
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
return 0;
|
|
2850
|
+
};
|
|
2851
|
+
let i = 0;
|
|
2852
|
+
for (; i < children.length; i++) {
|
|
2853
|
+
const child = children[i];
|
|
2854
|
+
const hoisted = getHoistedNode(child);
|
|
2855
|
+
if (hoisted) {
|
|
2856
|
+
// presence of hoisted means child must be a stringifiable node
|
|
2857
|
+
const node = child;
|
|
2858
|
+
const result = analyzeNode(node);
|
|
2859
|
+
if (result) {
|
|
2860
|
+
// node is stringifiable, record state
|
|
2861
|
+
nc += result[0];
|
|
2862
|
+
ec += result[1];
|
|
2863
|
+
currentChunk.push(node);
|
|
2864
|
+
continue;
|
|
2865
|
+
}
|
|
2866
|
+
}
|
|
2867
|
+
// we only reach here if we ran into a node that is not stringifiable
|
|
2868
|
+
// check if currently analyzed nodes meet criteria for stringification.
|
|
2869
|
+
// adjust iteration index
|
|
2870
|
+
i -= stringifyCurrentChunk(i);
|
|
2871
|
+
// reset state
|
|
2872
|
+
nc = 0;
|
|
2873
|
+
ec = 0;
|
|
2874
|
+
currentChunk.length = 0;
|
|
2875
|
+
}
|
|
2876
|
+
// in case the last node was also stringifiable
|
|
2877
|
+
stringifyCurrentChunk(i);
|
|
2878
|
+
};
|
|
2879
|
+
const getHoistedNode = (node) => ((node.type === 1 /* NodeTypes.ELEMENT */ && node.tagType === 0 /* ElementTypes.ELEMENT */) ||
|
|
2880
|
+
node.type == 12 /* NodeTypes.TEXT_CALL */) &&
|
|
2881
|
+
node.codegenNode &&
|
|
2882
|
+
node.codegenNode.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */ &&
|
|
2883
|
+
node.codegenNode.hoisted;
|
|
2884
|
+
const dataAriaRE = /^(data|aria)-/;
|
|
2885
|
+
const isStringifiableAttr = (name, ns) => {
|
|
2886
|
+
return ((ns === 0 /* DOMNamespaces.HTML */
|
|
2887
|
+
? shared.isKnownHtmlAttr(name)
|
|
2888
|
+
: ns === 1 /* DOMNamespaces.SVG */
|
|
2889
|
+
? shared.isKnownSvgAttr(name)
|
|
2890
|
+
: false) || dataAriaRE.test(name));
|
|
2891
|
+
};
|
|
2892
|
+
const replaceHoist = (node, replacement, context) => {
|
|
2893
|
+
const hoistToReplace = node.codegenNode.hoisted;
|
|
2894
|
+
context.hoists[context.hoists.indexOf(hoistToReplace)] = replacement;
|
|
2895
|
+
};
|
|
2896
|
+
const isNonStringifiable = /*#__PURE__*/ shared.makeMap(`caption,thead,tr,th,tbody,td,tfoot,colgroup,col`);
|
|
2897
|
+
/**
|
|
2898
|
+
* for a hoisted node, analyze it and return:
|
|
2899
|
+
* - false: bailed (contains non-stringifiable props or runtime constant)
|
|
2900
|
+
* - [nc, ec] where
|
|
2901
|
+
* - nc is the number of nodes inside
|
|
2902
|
+
* - ec is the number of element with bindings inside
|
|
2903
|
+
*/
|
|
2904
|
+
function analyzeNode(node) {
|
|
2905
|
+
if (node.type === 1 /* NodeTypes.ELEMENT */ && isNonStringifiable(node.tag)) {
|
|
2906
|
+
return false;
|
|
2907
|
+
}
|
|
2908
|
+
if (node.type === 12 /* NodeTypes.TEXT_CALL */) {
|
|
2909
|
+
return [1, 0];
|
|
2910
|
+
}
|
|
2911
|
+
let nc = 1; // node count
|
|
2912
|
+
let ec = node.props.length > 0 ? 1 : 0; // element w/ binding count
|
|
2913
|
+
let bailed = false;
|
|
2914
|
+
const bail = () => {
|
|
2915
|
+
bailed = true;
|
|
2916
|
+
return false;
|
|
2917
|
+
};
|
|
2918
|
+
// TODO: check for cases where using innerHTML will result in different
|
|
2919
|
+
// output compared to imperative node insertions.
|
|
2920
|
+
// probably only need to check for most common case
|
|
2921
|
+
// i.e. non-phrasing-content tags inside `<p>`
|
|
2922
|
+
function walk(node) {
|
|
2923
|
+
for (let i = 0; i < node.props.length; i++) {
|
|
2924
|
+
const p = node.props[i];
|
|
2925
|
+
// bail on non-attr bindings
|
|
2926
|
+
if (p.type === 6 /* NodeTypes.ATTRIBUTE */ &&
|
|
2927
|
+
!isStringifiableAttr(p.name, node.ns)) {
|
|
2928
|
+
return bail();
|
|
2929
|
+
}
|
|
2930
|
+
if (p.type === 7 /* NodeTypes.DIRECTIVE */ && p.name === 'bind') {
|
|
2931
|
+
// bail on non-attr bindings
|
|
2932
|
+
if (p.arg &&
|
|
2933
|
+
(p.arg.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */ ||
|
|
2934
|
+
(p.arg.isStatic && !isStringifiableAttr(p.arg.content, node.ns)))) {
|
|
2935
|
+
return bail();
|
|
2936
|
+
}
|
|
2937
|
+
if (p.exp &&
|
|
2938
|
+
(p.exp.type === 8 /* NodeTypes.COMPOUND_EXPRESSION */ ||
|
|
2939
|
+
p.exp.constType < 3 /* ConstantTypes.CAN_STRINGIFY */)) {
|
|
2940
|
+
return bail();
|
|
2941
|
+
}
|
|
2942
|
+
}
|
|
2943
|
+
}
|
|
2944
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
2945
|
+
nc++;
|
|
2946
|
+
const child = node.children[i];
|
|
2947
|
+
if (child.type === 1 /* NodeTypes.ELEMENT */) {
|
|
2948
|
+
if (child.props.length > 0) {
|
|
2949
|
+
ec++;
|
|
2950
|
+
}
|
|
2951
|
+
walk(child);
|
|
2952
|
+
if (bailed) {
|
|
2953
|
+
return false;
|
|
2954
|
+
}
|
|
2955
|
+
}
|
|
2956
|
+
}
|
|
2957
|
+
return true;
|
|
2958
|
+
}
|
|
2959
|
+
return walk(node) ? [nc, ec] : false;
|
|
2960
|
+
}
|
|
2961
|
+
function stringifyNode(node, context) {
|
|
2962
|
+
if (shared.isString(node)) {
|
|
2963
|
+
return node;
|
|
2964
|
+
}
|
|
2965
|
+
if (shared.isSymbol(node)) {
|
|
2966
|
+
return ``;
|
|
2967
|
+
}
|
|
2968
|
+
switch (node.type) {
|
|
2969
|
+
case 1 /* NodeTypes.ELEMENT */:
|
|
2970
|
+
return stringifyElement(node, context);
|
|
2971
|
+
case 2 /* NodeTypes.TEXT */:
|
|
2972
|
+
return shared.escapeHtml(node.content);
|
|
2973
|
+
case 3 /* NodeTypes.COMMENT */:
|
|
2974
|
+
return `<!--${shared.escapeHtml(node.content)}-->`;
|
|
2975
|
+
case 5 /* NodeTypes.INTERPOLATION */:
|
|
2976
|
+
return shared.escapeHtml(shared.toDisplayString(evaluateConstant(node.content)));
|
|
2977
|
+
case 8 /* NodeTypes.COMPOUND_EXPRESSION */:
|
|
2978
|
+
return shared.escapeHtml(evaluateConstant(node));
|
|
2979
|
+
case 12 /* NodeTypes.TEXT_CALL */:
|
|
2980
|
+
return stringifyNode(node.content, context);
|
|
2981
|
+
default:
|
|
2982
|
+
// static trees will not contain if/for nodes
|
|
2983
|
+
return '';
|
|
2984
|
+
}
|
|
2985
|
+
}
|
|
2986
|
+
function stringifyElement(node, context) {
|
|
2987
|
+
let res = `<${node.tag}`;
|
|
2988
|
+
let innerHTML = '';
|
|
2989
|
+
for (let i = 0; i < node.props.length; i++) {
|
|
2990
|
+
const p = node.props[i];
|
|
2991
|
+
if (p.type === 6 /* NodeTypes.ATTRIBUTE */) {
|
|
2992
|
+
res += ` ${p.name}`;
|
|
2993
|
+
if (p.value) {
|
|
2994
|
+
res += `="${shared.escapeHtml(p.value.content)}"`;
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
else if (p.type === 7 /* NodeTypes.DIRECTIVE */) {
|
|
2998
|
+
if (p.name === 'bind') {
|
|
2999
|
+
const exp = p.exp;
|
|
3000
|
+
if (exp.content[0] === '_') {
|
|
3001
|
+
// internally generated string constant references
|
|
3002
|
+
// e.g. imported URL strings via compiler-sfc transformAssetUrl plugin
|
|
3003
|
+
res += ` ${p.arg.content}="__VUE_EXP_START__${exp.content}__VUE_EXP_END__"`;
|
|
3004
|
+
continue;
|
|
3005
|
+
}
|
|
3006
|
+
// #6568
|
|
3007
|
+
if (shared.isBooleanAttr(p.arg.content) &&
|
|
3008
|
+
exp.content === 'false') {
|
|
3009
|
+
continue;
|
|
3010
|
+
}
|
|
3011
|
+
// constant v-bind, e.g. :foo="1"
|
|
3012
|
+
let evaluated = evaluateConstant(exp);
|
|
3013
|
+
if (evaluated != null) {
|
|
3014
|
+
const arg = p.arg && p.arg.content;
|
|
3015
|
+
if (arg === 'class') {
|
|
3016
|
+
evaluated = shared.normalizeClass(evaluated);
|
|
3017
|
+
}
|
|
3018
|
+
else if (arg === 'style') {
|
|
3019
|
+
evaluated = shared.stringifyStyle(shared.normalizeStyle(evaluated));
|
|
3020
|
+
}
|
|
3021
|
+
res += ` ${p.arg.content}="${shared.escapeHtml(evaluated)}"`;
|
|
3022
|
+
}
|
|
3023
|
+
}
|
|
3024
|
+
else if (p.name === 'html') {
|
|
3025
|
+
// #5439 v-html with constant value
|
|
3026
|
+
// not sure why would anyone do this but it can happen
|
|
3027
|
+
innerHTML = evaluateConstant(p.exp);
|
|
3028
|
+
}
|
|
3029
|
+
else if (p.name === 'text') {
|
|
3030
|
+
innerHTML = shared.escapeHtml(shared.toDisplayString(evaluateConstant(p.exp)));
|
|
3031
|
+
}
|
|
3032
|
+
}
|
|
3033
|
+
}
|
|
3034
|
+
if (context.scopeId) {
|
|
3035
|
+
res += ` ${context.scopeId}`;
|
|
3036
|
+
}
|
|
3037
|
+
res += `>`;
|
|
3038
|
+
if (innerHTML) {
|
|
3039
|
+
res += innerHTML;
|
|
3040
|
+
}
|
|
3041
|
+
else {
|
|
3042
|
+
for (let i = 0; i < node.children.length; i++) {
|
|
3043
|
+
res += stringifyNode(node.children[i], context);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
if (!shared.isVoidTag(node.tag)) {
|
|
3047
|
+
res += `</${node.tag}>`;
|
|
3048
|
+
}
|
|
3049
|
+
return res;
|
|
3050
|
+
}
|
|
3051
|
+
// __UNSAFE__
|
|
3052
|
+
// Reason: eval.
|
|
3053
|
+
// It's technically safe to eval because only constant expressions are possible
|
|
3054
|
+
// here, e.g. `{{ 1 }}` or `{{ 'foo' }}`
|
|
3055
|
+
// in addition, constant exps bail on presence of parens so you can't even
|
|
3056
|
+
// run JSFuck in here. But we mark it unsafe for security review purposes.
|
|
3057
|
+
// (see compiler-core/src/transforms/transformExpression)
|
|
3058
|
+
function evaluateConstant(exp) {
|
|
3059
|
+
if (exp.type === 4 /* NodeTypes.SIMPLE_EXPRESSION */) {
|
|
3060
|
+
return new Function(`return ${exp.content}`)();
|
|
3061
|
+
}
|
|
3062
|
+
else {
|
|
3063
|
+
// compound
|
|
3064
|
+
let res = ``;
|
|
3065
|
+
exp.children.forEach(c => {
|
|
3066
|
+
if (shared.isString(c) || shared.isSymbol(c)) {
|
|
3067
|
+
return;
|
|
3068
|
+
}
|
|
3069
|
+
if (c.type === 2 /* NodeTypes.TEXT */) {
|
|
3070
|
+
res += c.content;
|
|
3071
|
+
}
|
|
3072
|
+
else if (c.type === 5 /* NodeTypes.INTERPOLATION */) {
|
|
3073
|
+
res += shared.toDisplayString(evaluateConstant(c.content));
|
|
3074
|
+
}
|
|
3075
|
+
else {
|
|
3076
|
+
res += evaluateConstant(c);
|
|
3077
|
+
}
|
|
3078
|
+
});
|
|
3079
|
+
return res;
|
|
3080
|
+
}
|
|
3081
3081
|
}
|
|
3082
3082
|
|
|
3083
|
-
const ignoreSideEffectTags = (node, context) => {
|
|
3084
|
-
if (node.type === 1 /* NodeTypes.ELEMENT */ &&
|
|
3085
|
-
node.tagType === 0 /* ElementTypes.ELEMENT */ &&
|
|
3086
|
-
(node.tag === 'script' || node.tag === 'style')) {
|
|
3087
|
-
context.onError(createDOMCompilerError(60 /* DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG */, node.loc));
|
|
3088
|
-
context.removeNode();
|
|
3089
|
-
}
|
|
3083
|
+
const ignoreSideEffectTags = (node, context) => {
|
|
3084
|
+
if (node.type === 1 /* NodeTypes.ELEMENT */ &&
|
|
3085
|
+
node.tagType === 0 /* ElementTypes.ELEMENT */ &&
|
|
3086
|
+
(node.tag === 'script' || node.tag === 'style')) {
|
|
3087
|
+
context.onError(createDOMCompilerError(60 /* DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG */, node.loc));
|
|
3088
|
+
context.removeNode();
|
|
3089
|
+
}
|
|
3090
3090
|
};
|
|
3091
3091
|
|
|
3092
|
-
const DOMNodeTransforms = [
|
|
3093
|
-
transformStyle,
|
|
3094
|
-
...([transformTransition] )
|
|
3095
|
-
];
|
|
3096
|
-
const DOMDirectiveTransforms = {
|
|
3097
|
-
cloak: compilerCore.noopDirectiveTransform,
|
|
3098
|
-
html: transformVHtml,
|
|
3099
|
-
text: transformVText,
|
|
3100
|
-
model: transformModel,
|
|
3101
|
-
on: transformOn,
|
|
3102
|
-
show: transformShow
|
|
3103
|
-
};
|
|
3104
|
-
function compile(template, options = {}) {
|
|
3105
|
-
return compilerCore.baseCompile(template, shared.extend({}, parserOptions, options, {
|
|
3106
|
-
nodeTransforms: [
|
|
3107
|
-
// ignore <script> and <tag>
|
|
3108
|
-
// this is not put inside DOMNodeTransforms because that list is used
|
|
3109
|
-
// by compiler-ssr to generate vnode fallback branches
|
|
3110
|
-
ignoreSideEffectTags,
|
|
3111
|
-
...DOMNodeTransforms,
|
|
3112
|
-
...(options.nodeTransforms || [])
|
|
3113
|
-
],
|
|
3114
|
-
directiveTransforms: shared.extend({}, DOMDirectiveTransforms, options.directiveTransforms || {}),
|
|
3115
|
-
transformHoist: stringifyStatic
|
|
3116
|
-
}));
|
|
3117
|
-
}
|
|
3118
|
-
function parse(template, options = {}) {
|
|
3119
|
-
return compilerCore.baseParse(template, shared.extend({}, parserOptions, options));
|
|
3092
|
+
const DOMNodeTransforms = [
|
|
3093
|
+
transformStyle,
|
|
3094
|
+
...([transformTransition] )
|
|
3095
|
+
];
|
|
3096
|
+
const DOMDirectiveTransforms = {
|
|
3097
|
+
cloak: compilerCore.noopDirectiveTransform,
|
|
3098
|
+
html: transformVHtml,
|
|
3099
|
+
text: transformVText,
|
|
3100
|
+
model: transformModel,
|
|
3101
|
+
on: transformOn,
|
|
3102
|
+
show: transformShow
|
|
3103
|
+
};
|
|
3104
|
+
function compile(template, options = {}) {
|
|
3105
|
+
return compilerCore.baseCompile(template, shared.extend({}, parserOptions, options, {
|
|
3106
|
+
nodeTransforms: [
|
|
3107
|
+
// ignore <script> and <tag>
|
|
3108
|
+
// this is not put inside DOMNodeTransforms because that list is used
|
|
3109
|
+
// by compiler-ssr to generate vnode fallback branches
|
|
3110
|
+
ignoreSideEffectTags,
|
|
3111
|
+
...DOMNodeTransforms,
|
|
3112
|
+
...(options.nodeTransforms || [])
|
|
3113
|
+
],
|
|
3114
|
+
directiveTransforms: shared.extend({}, DOMDirectiveTransforms, options.directiveTransforms || {}),
|
|
3115
|
+
transformHoist: stringifyStatic
|
|
3116
|
+
}));
|
|
3117
|
+
}
|
|
3118
|
+
function parse(template, options = {}) {
|
|
3119
|
+
return compilerCore.baseParse(template, shared.extend({}, parserOptions, options));
|
|
3120
3120
|
}
|
|
3121
3121
|
|
|
3122
3122
|
Object.keys(compilerCore).forEach(function (k) {
|