mirror of https://github.com/vuejs/core.git
style: update format & lint config (#9162)
Co-authored-by: 丶远方 <yangpanteng@gmail.com> Co-authored-by: 三咲智子 Kevin Deng <sxzz@sxzz.moe> Co-authored-by: Guo Xingjun <99574369+Plumbiu@users.noreply.github.com>
This commit is contained in:
parent
baf0b7664d
commit
bfe6b459d3
|
@ -1,12 +1,11 @@
|
||||||
/* eslint-disable no-restricted-globals */
|
const { builtinModules } = require('node:module')
|
||||||
|
|
||||||
const DOMGlobals = ['window', 'document']
|
const DOMGlobals = ['window', 'document']
|
||||||
const NodeGlobals = ['module', 'require']
|
const NodeGlobals = ['module', 'require']
|
||||||
|
|
||||||
const banConstEnum = {
|
const banConstEnum = {
|
||||||
selector: 'TSEnumDeclaration[const=true]',
|
selector: 'TSEnumDeclaration[const=true]',
|
||||||
message:
|
message:
|
||||||
'Please use non-const enums. This project automatically inlines enums.'
|
'Please use non-const enums. This project automatically inlines enums.',
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,9 +14,9 @@ const banConstEnum = {
|
||||||
module.exports = {
|
module.exports = {
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
parserOptions: {
|
parserOptions: {
|
||||||
sourceType: 'module'
|
sourceType: 'module',
|
||||||
},
|
},
|
||||||
plugins: ['jest'],
|
plugins: ['jest', 'import', '@typescript-eslint'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-debugger': 'error',
|
'no-debugger': 'error',
|
||||||
// most of the codebase are expected to be env agnostic
|
// most of the codebase are expected to be env agnostic
|
||||||
|
@ -32,8 +31,27 @@ module.exports = {
|
||||||
// tsc compiles assignment spread into Object.assign() calls, but esbuild
|
// tsc compiles assignment spread into Object.assign() calls, but esbuild
|
||||||
// still generates verbose helpers, so spread assignment is also prohiboted
|
// still generates verbose helpers, so spread assignment is also prohiboted
|
||||||
'ObjectExpression > SpreadElement',
|
'ObjectExpression > SpreadElement',
|
||||||
'AwaitExpression'
|
'AwaitExpression',
|
||||||
]
|
],
|
||||||
|
'sort-imports': ['error', { ignoreDeclarationSort: true }],
|
||||||
|
|
||||||
|
'import/no-nodejs-modules': [
|
||||||
|
'error',
|
||||||
|
{ allow: builtinModules.map(mod => `node:${mod}`) },
|
||||||
|
],
|
||||||
|
// This rule enforces the preference for using '@ts-expect-error' comments in TypeScript
|
||||||
|
// code to indicate intentional type errors, improving code clarity and maintainability.
|
||||||
|
'@typescript-eslint/prefer-ts-expect-error': 'error',
|
||||||
|
// Enforce the use of 'import type' for importing types
|
||||||
|
'@typescript-eslint/consistent-type-imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
fixStyle: 'inline-type-imports',
|
||||||
|
disallowTypeAnnotations: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers
|
||||||
|
'@typescript-eslint/no-import-type-side-effects': 'error',
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
// tests, no restrictions (runs in Node / jest with jsdom)
|
// tests, no restrictions (runs in Node / jest with jsdom)
|
||||||
|
@ -43,54 +61,66 @@ module.exports = {
|
||||||
'no-restricted-globals': 'off',
|
'no-restricted-globals': 'off',
|
||||||
'no-restricted-syntax': 'off',
|
'no-restricted-syntax': 'off',
|
||||||
'jest/no-disabled-tests': 'error',
|
'jest/no-disabled-tests': 'error',
|
||||||
'jest/no-focused-tests': 'error'
|
'jest/no-focused-tests': 'error',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// shared, may be used in any env
|
// shared, may be used in any env
|
||||||
{
|
{
|
||||||
files: ['packages/shared/**'],
|
files: ['packages/shared/**', '.eslintrc.cjs'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-restricted-globals': 'off'
|
'no-restricted-globals': 'off',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// Packages targeting DOM
|
// Packages targeting DOM
|
||||||
{
|
{
|
||||||
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
|
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-restricted-globals': ['error', ...NodeGlobals]
|
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// Packages targeting Node
|
// Packages targeting Node
|
||||||
{
|
{
|
||||||
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
|
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-restricted-globals': ['error', ...DOMGlobals],
|
'no-restricted-globals': ['error', ...DOMGlobals],
|
||||||
'no-restricted-syntax': ['error', banConstEnum]
|
'no-restricted-syntax': ['error', banConstEnum],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// Private package, browser only + no syntax restrictions
|
// Private package, browser only + no syntax restrictions
|
||||||
{
|
{
|
||||||
files: ['packages/template-explorer/**', 'packages/sfc-playground/**'],
|
files: ['packages/template-explorer/**', 'packages/sfc-playground/**'],
|
||||||
rules: {
|
rules: {
|
||||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||||
'no-restricted-syntax': ['error', banConstEnum]
|
'no-restricted-syntax': ['error', banConstEnum],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// JavaScript files
|
// JavaScript files
|
||||||
{
|
{
|
||||||
files: ['*.js', '*.cjs'],
|
files: ['*.js', '*.cjs'],
|
||||||
rules: {
|
rules: {
|
||||||
// We only do `no-unused-vars` checks for js files, TS files are checked by TypeScript itself.
|
// We only do `no-unused-vars` checks for js files, TS files are checked by TypeScript itself.
|
||||||
'no-unused-vars': ['error', { vars: 'all', args: 'none' }]
|
'no-unused-vars': ['error', { vars: 'all', args: 'none' }],
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// Node scripts
|
// Node scripts
|
||||||
{
|
{
|
||||||
files: ['scripts/**', '*.{js,ts}', 'packages/**/index.js'],
|
files: [
|
||||||
|
'scripts/**',
|
||||||
|
'./*.{js,ts}',
|
||||||
|
'packages/*/*.js',
|
||||||
|
'packages/vue/*/*.js',
|
||||||
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'no-restricted-globals': 'off',
|
'no-restricted-globals': 'off',
|
||||||
'no-restricted-syntax': ['error', banConstEnum]
|
'no-restricted-syntax': ['error', banConstEnum],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
// Import nodejs modules in compiler-sfc
|
||||||
|
{
|
||||||
|
files: ['packages/compiler-sfc/src/**'],
|
||||||
|
rules: {
|
||||||
|
'import/no-nodejs-modules': ['error', { allow: builtinModules }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,35 +7,35 @@
|
||||||
packageRules: [
|
packageRules: [
|
||||||
{
|
{
|
||||||
depTypeList: ['peerDependencies'],
|
depTypeList: ['peerDependencies'],
|
||||||
enabled: false
|
enabled: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
groupName: 'test',
|
groupName: 'test',
|
||||||
matchPackageNames: ['vitest', 'jsdom', 'puppeteer'],
|
matchPackageNames: ['vitest', 'jsdom', 'puppeteer'],
|
||||||
matchPackagePrefixes: ['@vitest']
|
matchPackagePrefixes: ['@vitest'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
groupName: 'playground',
|
groupName: 'playground',
|
||||||
matchFileNames: [
|
matchFileNames: [
|
||||||
'packages/sfc-playground/package.json',
|
'packages/sfc-playground/package.json',
|
||||||
'packages/template-explorer/package.json'
|
'packages/template-explorer/package.json',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
groupName: 'compiler',
|
groupName: 'compiler',
|
||||||
matchPackageNames: ['magic-string'],
|
matchPackageNames: ['magic-string'],
|
||||||
matchPackagePrefixes: ['@babel', 'postcss']
|
matchPackagePrefixes: ['@babel', 'postcss'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
groupName: 'build',
|
groupName: 'build',
|
||||||
matchPackageNames: ['vite', 'terser'],
|
matchPackageNames: ['vite', 'terser'],
|
||||||
matchPackagePrefixes: ['rollup', 'esbuild', '@rollup', '@vitejs']
|
matchPackagePrefixes: ['rollup', 'esbuild', '@rollup', '@vitejs'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
groupName: 'lint',
|
groupName: 'lint',
|
||||||
matchPackageNames: ['simple-git-hooks', 'lint-staged'],
|
matchPackageNames: ['simple-git-hooks', 'lint-staged'],
|
||||||
matchPackagePrefixes: ['@typescript-eslint', 'eslint', 'prettier']
|
matchPackagePrefixes: ['@typescript-eslint', 'eslint', 'prettier'],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
ignoreDeps: [
|
ignoreDeps: [
|
||||||
'vue',
|
'vue',
|
||||||
|
@ -45,6 +45,6 @@
|
||||||
'typescript',
|
'typescript',
|
||||||
|
|
||||||
// ESM only
|
// ESM only
|
||||||
'estree-walker'
|
'estree-walker',
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
dist
|
dist
|
||||||
|
*.md
|
||||||
|
*.html
|
||||||
|
pnpm-lock.yaml
|
||||||
|
|
10
.prettierrc
10
.prettierrc
|
@ -1,5 +1,5 @@
|
||||||
semi: false
|
{
|
||||||
singleQuote: true
|
"semi": false,
|
||||||
printWidth: 80
|
"singleQuote": true,
|
||||||
trailingComma: 'none'
|
"arrowParens": "avoid"
|
||||||
arrowParens: 'avoid'
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"sourceMaps": true,
|
"sourceMaps": true,
|
||||||
"windows": {
|
"windows": {
|
||||||
"program": "${workspaceFolder}/node_modules/jest/bin/jest",
|
"program": "${workspaceFolder}/node_modules/jest/bin/jest"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
|
"size-esm-runtime": "node scripts/build.js vue -f esm-bundler-runtime",
|
||||||
"size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
|
"size-esm": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
|
||||||
"check": "tsc --incremental --noEmit",
|
"check": "tsc --incremental --noEmit",
|
||||||
"lint": "eslint --cache --ext .ts packages/*/{src,__tests__}/**.ts",
|
"lint": "eslint --cache --ext .js,.ts,.tsx .",
|
||||||
"format": "prettier --write --cache \"**/*.[tj]s?(x)\"",
|
"format": "prettier --write --cache .",
|
||||||
"format-check": "prettier --check --cache \"**/*.[tj]s?(x)\"",
|
"format-check": "prettier --check --cache .",
|
||||||
"test": "vitest",
|
"test": "vitest",
|
||||||
"test-unit": "vitest -c vitest.unit.config.ts",
|
"test-unit": "vitest -c vitest.unit.config.ts",
|
||||||
"test-e2e": "node scripts/build.js vue -f global -d && vitest -c vitest.e2e.config.ts",
|
"test-e2e": "node scripts/build.js vue -f global -d && vitest -c vitest.e2e.config.ts",
|
||||||
|
@ -72,6 +72,7 @@
|
||||||
"@types/minimist": "^1.2.5",
|
"@types/minimist": "^1.2.5",
|
||||||
"@types/node": "^20.10.5",
|
"@types/node": "^20.10.5",
|
||||||
"@types/semver": "^7.5.5",
|
"@types/semver": "^7.5.5",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.16.0",
|
||||||
"@typescript-eslint/parser": "^6.15.0",
|
"@typescript-eslint/parser": "^6.15.0",
|
||||||
"@vitest/coverage-istanbul": "^1.1.0",
|
"@vitest/coverage-istanbul": "^1.1.0",
|
||||||
"@vue/consolidate": "0.17.3",
|
"@vue/consolidate": "0.17.3",
|
||||||
|
@ -81,6 +82,7 @@
|
||||||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-define-config": "^1.24.1",
|
"eslint-define-config": "^1.24.1",
|
||||||
|
"eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
|
||||||
"eslint-plugin-jest": "^27.6.0",
|
"eslint-plugin-jest": "^27.6.0",
|
||||||
"estree-walker": "^2.0.2",
|
"estree-walker": "^2.0.2",
|
||||||
"execa": "^8.0.1",
|
"execa": "^8.0.1",
|
||||||
|
|
|
@ -1,38 +1,38 @@
|
||||||
import {
|
import {
|
||||||
locStub,
|
ConstantTypes,
|
||||||
generate,
|
type DirectiveArguments,
|
||||||
|
type ForCodegenNode,
|
||||||
|
type IfConditionalExpression,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
RootNode,
|
type RootNode,
|
||||||
createSimpleExpression,
|
type VNodeCall,
|
||||||
|
createArrayExpression,
|
||||||
|
createAssignmentExpression,
|
||||||
|
createBlockStatement,
|
||||||
|
createCacheExpression,
|
||||||
|
createCallExpression,
|
||||||
|
createCompoundExpression,
|
||||||
|
createConditionalExpression,
|
||||||
|
createIfStatement,
|
||||||
|
createInterpolation,
|
||||||
createObjectExpression,
|
createObjectExpression,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createArrayExpression,
|
createSimpleExpression,
|
||||||
createCompoundExpression,
|
|
||||||
createInterpolation,
|
|
||||||
createCallExpression,
|
|
||||||
createConditionalExpression,
|
|
||||||
ForCodegenNode,
|
|
||||||
createCacheExpression,
|
|
||||||
createTemplateLiteral,
|
createTemplateLiteral,
|
||||||
createBlockStatement,
|
|
||||||
createIfStatement,
|
|
||||||
createAssignmentExpression,
|
|
||||||
IfConditionalExpression,
|
|
||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
VNodeCall,
|
generate,
|
||||||
DirectiveArguments,
|
locStub,
|
||||||
ConstantTypes
|
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import {
|
import {
|
||||||
CREATE_VNODE,
|
|
||||||
TO_DISPLAY_STRING,
|
|
||||||
RESOLVE_DIRECTIVE,
|
|
||||||
helperNameMap,
|
|
||||||
RESOLVE_COMPONENT,
|
|
||||||
CREATE_COMMENT,
|
CREATE_COMMENT,
|
||||||
|
CREATE_ELEMENT_VNODE,
|
||||||
|
CREATE_VNODE,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
RENDER_LIST,
|
RENDER_LIST,
|
||||||
CREATE_ELEMENT_VNODE
|
RESOLVE_COMPONENT,
|
||||||
|
RESOLVE_DIRECTIVE,
|
||||||
|
TO_DISPLAY_STRING,
|
||||||
|
helperNameMap,
|
||||||
} from '../src/runtimeHelpers'
|
} from '../src/runtimeHelpers'
|
||||||
import { createElementWithCodegen, genFlagText } from './testUtils'
|
import { createElementWithCodegen, genFlagText } from './testUtils'
|
||||||
import { PatchFlags } from '@vue/shared'
|
import { PatchFlags } from '@vue/shared'
|
||||||
|
@ -51,59 +51,59 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
|
||||||
temps: 0,
|
temps: 0,
|
||||||
codegenNode: createSimpleExpression(`null`, false),
|
codegenNode: createSimpleExpression(`null`, false),
|
||||||
loc: locStub,
|
loc: locStub,
|
||||||
...options
|
...options,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('compiler: codegen', () => {
|
describe('compiler: codegen', () => {
|
||||||
test('module mode preamble', () => {
|
test('module mode preamble', () => {
|
||||||
const root = createRoot({
|
const root = createRoot({
|
||||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
|
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),
|
||||||
})
|
})
|
||||||
const { code } = generate(root, { mode: 'module' })
|
const { code } = generate(root, { mode: 'module' })
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`import { ${helperNameMap[CREATE_VNODE]} as _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} as _${helperNameMap[RESOLVE_DIRECTIVE]} } from "vue"`
|
`import { ${helperNameMap[CREATE_VNODE]} as _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} as _${helperNameMap[RESOLVE_DIRECTIVE]} } from "vue"`,
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('module mode preamble w/ optimizeImports: true', () => {
|
test('module mode preamble w/ optimizeImports: true', () => {
|
||||||
const root = createRoot({
|
const root = createRoot({
|
||||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
|
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),
|
||||||
})
|
})
|
||||||
const { code } = generate(root, { mode: 'module', optimizeImports: true })
|
const { code } = generate(root, { mode: 'module', optimizeImports: true })
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`import { ${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} } from "vue"`
|
`import { ${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} } from "vue"`,
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const _${helperNameMap[CREATE_VNODE]} = ${helperNameMap[CREATE_VNODE]}, _${helperNameMap[RESOLVE_DIRECTIVE]} = ${helperNameMap[RESOLVE_DIRECTIVE]}`
|
`const _${helperNameMap[CREATE_VNODE]} = ${helperNameMap[CREATE_VNODE]}, _${helperNameMap[RESOLVE_DIRECTIVE]} = ${helperNameMap[RESOLVE_DIRECTIVE]}`,
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('function mode preamble', () => {
|
test('function mode preamble', () => {
|
||||||
const root = createRoot({
|
const root = createRoot({
|
||||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
|
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),
|
||||||
})
|
})
|
||||||
const { code } = generate(root, { mode: 'function' })
|
const { code } = generate(root, { mode: 'function' })
|
||||||
expect(code).toMatch(`const _Vue = Vue`)
|
expect(code).toMatch(`const _Vue = Vue`)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const { ${helperNameMap[CREATE_VNODE]}: _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${helperNameMap[RESOLVE_DIRECTIVE]} } = _Vue`
|
`const { ${helperNameMap[CREATE_VNODE]}: _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${helperNameMap[RESOLVE_DIRECTIVE]} } = _Vue`,
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('function mode preamble w/ prefixIdentifiers: true', () => {
|
test('function mode preamble w/ prefixIdentifiers: true', () => {
|
||||||
const root = createRoot({
|
const root = createRoot({
|
||||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
|
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),
|
||||||
})
|
})
|
||||||
const { code } = generate(root, {
|
const { code } = generate(root, {
|
||||||
mode: 'function',
|
mode: 'function',
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(code).not.toMatch(`const _Vue = Vue`)
|
expect(code).not.toMatch(`const _Vue = Vue`)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const { ${helperNameMap[CREATE_VNODE]}: _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${helperNameMap[RESOLVE_DIRECTIVE]} } = Vue`
|
`const { ${helperNameMap[CREATE_VNODE]}: _${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]}: _${helperNameMap[RESOLVE_DIRECTIVE]} } = Vue`,
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -112,27 +112,27 @@ describe('compiler: codegen', () => {
|
||||||
const root = createRoot({
|
const root = createRoot({
|
||||||
components: [`Foo`, `bar-baz`, `barbaz`, `Qux__self`],
|
components: [`Foo`, `bar-baz`, `barbaz`, `Qux__self`],
|
||||||
directives: [`my_dir_0`, `my_dir_1`],
|
directives: [`my_dir_0`, `my_dir_1`],
|
||||||
temps: 3
|
temps: 3,
|
||||||
})
|
})
|
||||||
const { code } = generate(root, { mode: 'function' })
|
const { code } = generate(root, { mode: 'function' })
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n`
|
`const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n`,
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const _component_bar_baz = _${helperNameMap[RESOLVE_COMPONENT]}("bar-baz")\n`
|
`const _component_bar_baz = _${helperNameMap[RESOLVE_COMPONENT]}("bar-baz")\n`,
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const _component_barbaz = _${helperNameMap[RESOLVE_COMPONENT]}("barbaz")\n`
|
`const _component_barbaz = _${helperNameMap[RESOLVE_COMPONENT]}("barbaz")\n`,
|
||||||
)
|
)
|
||||||
// implicit self reference from SFC filename
|
// implicit self reference from SFC filename
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const _component_Qux = _${helperNameMap[RESOLVE_COMPONENT]}("Qux", true)\n`
|
`const _component_Qux = _${helperNameMap[RESOLVE_COMPONENT]}("Qux", true)\n`,
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const _directive_my_dir_0 = _${helperNameMap[RESOLVE_DIRECTIVE]}("my_dir_0")\n`
|
`const _directive_my_dir_0 = _${helperNameMap[RESOLVE_DIRECTIVE]}("my_dir_0")\n`,
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`const _directive_my_dir_1 = _${helperNameMap[RESOLVE_DIRECTIVE]}("my_dir_1")\n`
|
`const _directive_my_dir_1 = _${helperNameMap[RESOLVE_DIRECTIVE]}("my_dir_1")\n`,
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`let _temp0, _temp1, _temp2`)
|
expect(code).toMatch(`let _temp0, _temp1, _temp2`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -146,12 +146,12 @@ describe('compiler: codegen', () => {
|
||||||
[
|
[
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression(`id`, true, locStub),
|
createSimpleExpression(`id`, true, locStub),
|
||||||
createSimpleExpression(`foo`, true, locStub)
|
createSimpleExpression(`foo`, true, locStub),
|
||||||
)
|
),
|
||||||
|
],
|
||||||
|
locStub,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
locStub
|
|
||||||
)
|
|
||||||
]
|
|
||||||
})
|
})
|
||||||
const { code } = generate(root)
|
const { code } = generate(root)
|
||||||
expect(code).toMatch(`const _hoisted_1 = hello`)
|
expect(code).toMatch(`const _hoisted_1 = hello`)
|
||||||
|
@ -161,7 +161,7 @@ describe('compiler: codegen', () => {
|
||||||
|
|
||||||
test('temps', () => {
|
test('temps', () => {
|
||||||
const root = createRoot({
|
const root = createRoot({
|
||||||
temps: 3
|
temps: 3,
|
||||||
})
|
})
|
||||||
const { code } = generate(root)
|
const { code } = generate(root)
|
||||||
expect(code).toMatch(`let _temp0, _temp1, _temp2`)
|
expect(code).toMatch(`let _temp0, _temp1, _temp2`)
|
||||||
|
@ -174,9 +174,9 @@ describe('compiler: codegen', () => {
|
||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: 'hello',
|
content: 'hello',
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`return "hello"`)
|
expect(code).toMatch(`return "hello"`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -185,8 +185,8 @@ describe('compiler: codegen', () => {
|
||||||
test('interpolation', () => {
|
test('interpolation', () => {
|
||||||
const { code } = generate(
|
const { code } = generate(
|
||||||
createRoot({
|
createRoot({
|
||||||
codegenNode: createInterpolation(`hello`, locStub)
|
codegenNode: createInterpolation(`hello`, locStub),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`return _${helperNameMap[TO_DISPLAY_STRING]}(hello)`)
|
expect(code).toMatch(`return _${helperNameMap[TO_DISPLAY_STRING]}(hello)`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -198,9 +198,9 @@ describe('compiler: codegen', () => {
|
||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.COMMENT,
|
type: NodeTypes.COMMENT,
|
||||||
content: 'foo',
|
content: 'foo',
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`return _${helperNameMap[CREATE_COMMENT]}("foo")`)
|
expect(code).toMatch(`return _${helperNameMap[CREATE_COMMENT]}("foo")`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -216,15 +216,15 @@ describe('compiler: codegen', () => {
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
loc: locStub,
|
loc: locStub,
|
||||||
content: createSimpleExpression(`bar`, false, locStub)
|
content: createSimpleExpression(`bar`, false, locStub),
|
||||||
},
|
},
|
||||||
// nested compound
|
// nested compound
|
||||||
createCompoundExpression([` + `, `nested`])
|
createCompoundExpression([` + `, `nested`]),
|
||||||
])
|
]),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`return _ctx.foo + _${helperNameMap[TO_DISPLAY_STRING]}(bar) + nested`
|
`return _ctx.foo + _${helperNameMap[TO_DISPLAY_STRING]}(bar) + nested`,
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -239,10 +239,10 @@ describe('compiler: codegen', () => {
|
||||||
codegenNode: createConditionalExpression(
|
codegenNode: createConditionalExpression(
|
||||||
createSimpleExpression('foo', false),
|
createSimpleExpression('foo', false),
|
||||||
createSimpleExpression('bar', false),
|
createSimpleExpression('bar', false),
|
||||||
createSimpleExpression('baz', false)
|
createSimpleExpression('baz', false),
|
||||||
) as IfConditionalExpression
|
) as IfConditionalExpression,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(/return foo\s+\? bar\s+: baz/)
|
expect(code).toMatch(/return foo\s+\? bar\s+: baz/)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -270,10 +270,10 @@ describe('compiler: codegen', () => {
|
||||||
patchFlag: '1',
|
patchFlag: '1',
|
||||||
dynamicProps: undefined,
|
dynamicProps: undefined,
|
||||||
directives: undefined,
|
directives: undefined,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
} as ForCodegenNode
|
} as ForCodegenNode,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`openBlock(true)`)
|
expect(code).toMatch(`openBlock(true)`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -289,7 +289,7 @@ describe('compiler: codegen', () => {
|
||||||
'1 + 2',
|
'1 + 2',
|
||||||
false,
|
false,
|
||||||
locStub,
|
locStub,
|
||||||
ConstantTypes.CAN_STRINGIFY
|
ConstantTypes.CAN_STRINGIFY,
|
||||||
),
|
),
|
||||||
valueAlias: undefined,
|
valueAlias: undefined,
|
||||||
keyAlias: undefined,
|
keyAlias: undefined,
|
||||||
|
@ -306,10 +306,10 @@ describe('compiler: codegen', () => {
|
||||||
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
|
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
|
||||||
dynamicProps: undefined,
|
dynamicProps: undefined,
|
||||||
directives: undefined,
|
directives: undefined,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
} as ForCodegenNode
|
} as ForCodegenNode,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`openBlock()`)
|
expect(code).toMatch(`openBlock()`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -326,11 +326,11 @@ describe('compiler: codegen', () => {
|
||||||
[
|
[
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression(`id`, true, locStub),
|
createSimpleExpression(`id`, true, locStub),
|
||||||
createSimpleExpression(`foo`, true, locStub)
|
createSimpleExpression(`foo`, true, locStub),
|
||||||
),
|
),
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression(`prop`, false, locStub),
|
createSimpleExpression(`prop`, false, locStub),
|
||||||
createSimpleExpression(`bar`, false, locStub)
|
createSimpleExpression(`bar`, false, locStub),
|
||||||
),
|
),
|
||||||
// compound expression as computed key
|
// compound expression as computed key
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
|
@ -339,13 +339,13 @@ describe('compiler: codegen', () => {
|
||||||
loc: locStub,
|
loc: locStub,
|
||||||
children: [
|
children: [
|
||||||
`foo + `,
|
`foo + `,
|
||||||
createSimpleExpression(`bar`, false, locStub)
|
createSimpleExpression(`bar`, false, locStub),
|
||||||
]
|
|
||||||
},
|
|
||||||
createSimpleExpression(`bar`, false, locStub)
|
|
||||||
)
|
|
||||||
],
|
],
|
||||||
locStub
|
},
|
||||||
|
createSimpleExpression(`bar`, false, locStub),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
locStub,
|
||||||
),
|
),
|
||||||
// ChildNode[]
|
// ChildNode[]
|
||||||
[
|
[
|
||||||
|
@ -356,17 +356,17 @@ describe('compiler: codegen', () => {
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
// should quote the key!
|
// should quote the key!
|
||||||
createSimpleExpression(`some-key`, true, locStub),
|
createSimpleExpression(`some-key`, true, locStub),
|
||||||
createSimpleExpression(`foo`, true, locStub)
|
createSimpleExpression(`foo`, true, locStub),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
locStub
|
locStub,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
// flag
|
// flag
|
||||||
PatchFlags.FULL_PROPS + ''
|
PatchFlags.FULL_PROPS + '',
|
||||||
)
|
),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`
|
expect(code).toMatch(`
|
||||||
return _${helperNameMap[CREATE_ELEMENT_VNODE]}("div", {
|
return _${helperNameMap[CREATE_ELEMENT_VNODE]}("div", {
|
||||||
|
@ -384,9 +384,9 @@ describe('compiler: codegen', () => {
|
||||||
createRoot({
|
createRoot({
|
||||||
codegenNode: createArrayExpression([
|
codegenNode: createArrayExpression([
|
||||||
createSimpleExpression(`foo`, false),
|
createSimpleExpression(`foo`, false),
|
||||||
createCallExpression(`bar`, [`baz`])
|
createCallExpression(`bar`, [`baz`]),
|
||||||
])
|
]),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`return [
|
expect(code).toMatch(`return [
|
||||||
foo,
|
foo,
|
||||||
|
@ -404,17 +404,17 @@ describe('compiler: codegen', () => {
|
||||||
createConditionalExpression(
|
createConditionalExpression(
|
||||||
createSimpleExpression(`orNot`, false),
|
createSimpleExpression(`orNot`, false),
|
||||||
createCallExpression(`bar`),
|
createCallExpression(`bar`),
|
||||||
createCallExpression(`baz`)
|
createCallExpression(`baz`),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`return ok
|
`return ok
|
||||||
? foo()
|
? foo()
|
||||||
: orNot
|
: orNot
|
||||||
? bar()
|
? bar()
|
||||||
: baz()`
|
: baz()`,
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -425,13 +425,13 @@ describe('compiler: codegen', () => {
|
||||||
cached: 1,
|
cached: 1,
|
||||||
codegenNode: createCacheExpression(
|
codegenNode: createCacheExpression(
|
||||||
1,
|
1,
|
||||||
createSimpleExpression(`foo`, false)
|
createSimpleExpression(`foo`, false),
|
||||||
)
|
),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`_cache[1] || (_cache[1] = foo)`)
|
expect(code).toMatch(`_cache[1] || (_cache[1] = foo)`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -444,13 +444,13 @@ describe('compiler: codegen', () => {
|
||||||
codegenNode: createCacheExpression(
|
codegenNode: createCacheExpression(
|
||||||
1,
|
1,
|
||||||
createSimpleExpression(`foo`, false),
|
createSimpleExpression(`foo`, false),
|
||||||
true
|
true,
|
||||||
)
|
),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`
|
`
|
||||||
|
@ -460,7 +460,7 @@ describe('compiler: codegen', () => {
|
||||||
_setBlockTracking(1),
|
_setBlockTracking(1),
|
||||||
_cache[1]
|
_cache[1]
|
||||||
)
|
)
|
||||||
`.trim()
|
`.trim(),
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -472,11 +472,11 @@ describe('compiler: codegen', () => {
|
||||||
createTemplateLiteral([
|
createTemplateLiteral([
|
||||||
`foo`,
|
`foo`,
|
||||||
createCallExpression(`_renderAttr`, ['id', 'foo']),
|
createCallExpression(`_renderAttr`, ['id', 'foo']),
|
||||||
`bar`
|
`bar`,
|
||||||
])
|
]),
|
||||||
])
|
]),
|
||||||
}),
|
}),
|
||||||
{ ssr: true, mode: 'module' }
|
{ ssr: true, mode: 'module' },
|
||||||
)
|
)
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
@ -493,11 +493,11 @@ describe('compiler: codegen', () => {
|
||||||
codegenNode: createBlockStatement([
|
codegenNode: createBlockStatement([
|
||||||
createIfStatement(
|
createIfStatement(
|
||||||
createSimpleExpression('foo', false),
|
createSimpleExpression('foo', false),
|
||||||
createBlockStatement([createCallExpression(`ok`)])
|
createBlockStatement([createCallExpression(`ok`)]),
|
||||||
)
|
),
|
||||||
])
|
]),
|
||||||
}),
|
}),
|
||||||
{ ssr: true, mode: 'module' }
|
{ ssr: true, mode: 'module' },
|
||||||
)
|
)
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
@ -516,11 +516,11 @@ describe('compiler: codegen', () => {
|
||||||
createIfStatement(
|
createIfStatement(
|
||||||
createSimpleExpression('foo', false),
|
createSimpleExpression('foo', false),
|
||||||
createBlockStatement([createCallExpression(`foo`)]),
|
createBlockStatement([createCallExpression(`foo`)]),
|
||||||
createBlockStatement([createCallExpression('bar')])
|
createBlockStatement([createCallExpression('bar')]),
|
||||||
)
|
),
|
||||||
])
|
]),
|
||||||
}),
|
}),
|
||||||
{ ssr: true, mode: 'module' }
|
{ ssr: true, mode: 'module' },
|
||||||
)
|
)
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
@ -543,12 +543,12 @@ describe('compiler: codegen', () => {
|
||||||
createBlockStatement([createCallExpression(`foo`)]),
|
createBlockStatement([createCallExpression(`foo`)]),
|
||||||
createIfStatement(
|
createIfStatement(
|
||||||
createSimpleExpression('bar', false),
|
createSimpleExpression('bar', false),
|
||||||
createBlockStatement([createCallExpression(`bar`)])
|
createBlockStatement([createCallExpression(`bar`)]),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
])
|
]),
|
||||||
}),
|
}),
|
||||||
{ ssr: true, mode: 'module' }
|
{ ssr: true, mode: 'module' },
|
||||||
)
|
)
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
@ -572,12 +572,12 @@ describe('compiler: codegen', () => {
|
||||||
createIfStatement(
|
createIfStatement(
|
||||||
createSimpleExpression('bar', false),
|
createSimpleExpression('bar', false),
|
||||||
createBlockStatement([createCallExpression(`bar`)]),
|
createBlockStatement([createCallExpression(`bar`)]),
|
||||||
createBlockStatement([createCallExpression('baz')])
|
createBlockStatement([createCallExpression('baz')]),
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
])
|
]),
|
||||||
}),
|
}),
|
||||||
{ ssr: true, mode: 'module' }
|
{ ssr: true, mode: 'module' },
|
||||||
)
|
)
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
@ -599,9 +599,9 @@ describe('compiler: codegen', () => {
|
||||||
createRoot({
|
createRoot({
|
||||||
codegenNode: createAssignmentExpression(
|
codegenNode: createAssignmentExpression(
|
||||||
createSimpleExpression(`foo`, false),
|
createSimpleExpression(`foo`, false),
|
||||||
createSimpleExpression(`bar`, false)
|
createSimpleExpression(`bar`, false),
|
||||||
)
|
),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
"
|
"
|
||||||
|
@ -617,17 +617,17 @@ describe('compiler: codegen', () => {
|
||||||
function genCode(node: VNodeCall) {
|
function genCode(node: VNodeCall) {
|
||||||
return generate(
|
return generate(
|
||||||
createRoot({
|
createRoot({
|
||||||
codegenNode: node
|
codegenNode: node,
|
||||||
})
|
}),
|
||||||
).code.match(/with \(_ctx\) \{\s+([^]+)\s+\}\s+\}$/)![1]
|
).code.match(/with \(_ctx\) \{\s+([^]+)\s+\}\s+\}$/)![1]
|
||||||
}
|
}
|
||||||
|
|
||||||
const mockProps = createObjectExpression([
|
const mockProps = createObjectExpression([
|
||||||
createObjectProperty(`foo`, createSimpleExpression(`bar`, true))
|
createObjectProperty(`foo`, createSimpleExpression(`bar`, true)),
|
||||||
])
|
])
|
||||||
const mockChildren = createCompoundExpression(['children'])
|
const mockChildren = createCompoundExpression(['children'])
|
||||||
const mockDirs = createArrayExpression([
|
const mockDirs = createArrayExpression([
|
||||||
createArrayExpression([`foo`, createSimpleExpression(`bar`, false)])
|
createArrayExpression([`foo`, createSimpleExpression(`bar`, false)]),
|
||||||
]) as DirectiveArguments
|
]) as DirectiveArguments
|
||||||
|
|
||||||
test('tag only', () => {
|
test('tag only', () => {
|
||||||
|
@ -684,9 +684,9 @@ describe('compiler: codegen', () => {
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
true
|
true,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"return (_openBlock(), _createElementBlock("div", { foo: "bar" }, children))
|
"return (_openBlock(), _createElementBlock("div", { foo: "bar" }, children))
|
||||||
"
|
"
|
||||||
|
@ -705,9 +705,9 @@ describe('compiler: codegen', () => {
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
true,
|
true,
|
||||||
true
|
true,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"return (_openBlock(true), _createElementBlock("div", { foo: "bar" }, children))
|
"return (_openBlock(true), _createElementBlock("div", { foo: "bar" }, children))
|
||||||
"
|
"
|
||||||
|
@ -724,9 +724,9 @@ describe('compiler: codegen', () => {
|
||||||
mockChildren,
|
mockChildren,
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
mockDirs
|
mockDirs,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"return _withDirectives(_createElementVNode("div", { foo: "bar" }, children), [
|
"return _withDirectives(_createElementVNode("div", { foo: "bar" }, children), [
|
||||||
[foo, bar]
|
[foo, bar]
|
||||||
|
@ -746,9 +746,9 @@ describe('compiler: codegen', () => {
|
||||||
undefined,
|
undefined,
|
||||||
undefined,
|
undefined,
|
||||||
mockDirs,
|
mockDirs,
|
||||||
true
|
true,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"return _withDirectives((_openBlock(), _createElementBlock("div", { foo: "bar" }, children)), [
|
"return _withDirectives((_openBlock(), _createElementBlock("div", { foo: "bar" }, children)), [
|
||||||
[foo, bar]
|
[foo, bar]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { baseCompile as compile } from '../src'
|
import { baseCompile as compile } from '../src'
|
||||||
import { SourceMapConsumer, RawSourceMap } from 'source-map-js'
|
import { type RawSourceMap, SourceMapConsumer } from 'source-map-js'
|
||||||
|
|
||||||
describe('compiler: integration tests', () => {
|
describe('compiler: integration tests', () => {
|
||||||
const source = `
|
const source = `
|
||||||
|
@ -20,7 +20,7 @@ describe('compiler: integration tests', () => {
|
||||||
function getPositionInCode(
|
function getPositionInCode(
|
||||||
code: string,
|
code: string,
|
||||||
token: string,
|
token: string,
|
||||||
expectName: string | boolean = false
|
expectName: string | boolean = false,
|
||||||
): Pos {
|
): Pos {
|
||||||
const generatedOffset = code.indexOf(token)
|
const generatedOffset = code.indexOf(token)
|
||||||
let line = 1
|
let line = 1
|
||||||
|
@ -36,7 +36,7 @@ describe('compiler: integration tests', () => {
|
||||||
column:
|
column:
|
||||||
lastNewLinePos === -1
|
lastNewLinePos === -1
|
||||||
? generatedOffset
|
? generatedOffset
|
||||||
: generatedOffset - lastNewLinePos - 1
|
: generatedOffset - lastNewLinePos - 1,
|
||||||
}
|
}
|
||||||
if (expectName) {
|
if (expectName) {
|
||||||
res.name = typeof expectName === 'string' ? expectName : token
|
res.name = typeof expectName === 'string' ? expectName : token
|
||||||
|
@ -47,7 +47,7 @@ describe('compiler: integration tests', () => {
|
||||||
test('function mode', () => {
|
test('function mode', () => {
|
||||||
const { code, map } = compile(source, {
|
const { code, map } = compile(source, {
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
filename: `foo.vue`
|
filename: `foo.vue`,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -57,55 +57,55 @@ describe('compiler: integration tests', () => {
|
||||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
consumer.originalPositionFor(getPositionInCode(code, `id`)),
|
||||||
).toMatchObject(getPositionInCode(source, `id`))
|
).toMatchObject(getPositionInCode(source, `id`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
consumer.originalPositionFor(getPositionInCode(code, `"foo"`)),
|
||||||
).toMatchObject(getPositionInCode(source, `"foo"`))
|
).toMatchObject(getPositionInCode(source, `"foo"`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
consumer.originalPositionFor(getPositionInCode(code, `class:`)),
|
||||||
).toMatchObject(getPositionInCode(source, `class=`))
|
).toMatchObject(getPositionInCode(source, `class=`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
consumer.originalPositionFor(getPositionInCode(code, `bar`)),
|
||||||
).toMatchObject(getPositionInCode(source, `bar`))
|
).toMatchObject(getPositionInCode(source, `bar`))
|
||||||
|
|
||||||
// without prefixIdentifiers: true, identifiers inside compound expressions
|
// without prefixIdentifiers: true, identifiers inside compound expressions
|
||||||
// are mapped to closest parent expression.
|
// are mapped to closest parent expression.
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
consumer.originalPositionFor(getPositionInCode(code, `baz`)),
|
||||||
).toMatchObject(getPositionInCode(source, `bar`))
|
).toMatchObject(getPositionInCode(source, `bar`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `world`))
|
consumer.originalPositionFor(getPositionInCode(code, `world`)),
|
||||||
).toMatchObject(getPositionInCode(source, `world`))
|
).toMatchObject(getPositionInCode(source, `world`))
|
||||||
|
|
||||||
// without prefixIdentifiers: true, identifiers inside compound expressions
|
// without prefixIdentifiers: true, identifiers inside compound expressions
|
||||||
// are mapped to closest parent expression.
|
// are mapped to closest parent expression.
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
consumer.originalPositionFor(getPositionInCode(code, `burn()`)),
|
||||||
).toMatchObject(getPositionInCode(source, `world`))
|
).toMatchObject(getPositionInCode(source, `world`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
consumer.originalPositionFor(getPositionInCode(code, `ok`)),
|
||||||
).toMatchObject(getPositionInCode(source, `ok`))
|
).toMatchObject(getPositionInCode(source, `ok`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
consumer.originalPositionFor(getPositionInCode(code, `list`)),
|
||||||
).toMatchObject(getPositionInCode(source, `list`))
|
).toMatchObject(getPositionInCode(source, `list`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
consumer.originalPositionFor(getPositionInCode(code, `value`)),
|
||||||
).toMatchObject(getPositionInCode(source, `value`))
|
).toMatchObject(getPositionInCode(source, `value`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
consumer.originalPositionFor(getPositionInCode(code, `index`)),
|
||||||
).toMatchObject(getPositionInCode(source, `index`))
|
).toMatchObject(getPositionInCode(source, `index`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
consumer.originalPositionFor(getPositionInCode(code, `value + index`)),
|
||||||
).toMatchObject(getPositionInCode(source, `value + index`))
|
).toMatchObject(getPositionInCode(source, `value + index`))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ describe('compiler: integration tests', () => {
|
||||||
const { code, map } = compile(source, {
|
const { code, map } = compile(source, {
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
filename: `foo.vue`,
|
filename: `foo.vue`,
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -123,64 +123,66 @@ describe('compiler: integration tests', () => {
|
||||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
consumer.originalPositionFor(getPositionInCode(code, `id`)),
|
||||||
).toMatchObject(getPositionInCode(source, `id`))
|
).toMatchObject(getPositionInCode(source, `id`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
consumer.originalPositionFor(getPositionInCode(code, `"foo"`)),
|
||||||
).toMatchObject(getPositionInCode(source, `"foo"`))
|
).toMatchObject(getPositionInCode(source, `"foo"`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
consumer.originalPositionFor(getPositionInCode(code, `class:`)),
|
||||||
).toMatchObject(getPositionInCode(source, `class=`))
|
).toMatchObject(getPositionInCode(source, `class=`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
consumer.originalPositionFor(getPositionInCode(code, `bar`)),
|
||||||
).toMatchObject(getPositionInCode(source, `bar`))
|
).toMatchObject(getPositionInCode(source, `bar`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`)),
|
||||||
).toMatchObject(getPositionInCode(source, `bar`, true))
|
).toMatchObject(getPositionInCode(source, `bar`, true))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
consumer.originalPositionFor(getPositionInCode(code, `baz`)),
|
||||||
).toMatchObject(getPositionInCode(source, `baz`))
|
).toMatchObject(getPositionInCode(source, `baz`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
|
consumer.originalPositionFor(getPositionInCode(code, `world`, true)),
|
||||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(
|
consumer.originalPositionFor(
|
||||||
getPositionInCode(code, `_ctx.world`, `world`)
|
getPositionInCode(code, `_ctx.world`, `world`),
|
||||||
)
|
),
|
||||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
consumer.originalPositionFor(getPositionInCode(code, `burn()`)),
|
||||||
).toMatchObject(getPositionInCode(source, `burn()`))
|
).toMatchObject(getPositionInCode(source, `burn()`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
consumer.originalPositionFor(getPositionInCode(code, `ok`)),
|
||||||
).toMatchObject(getPositionInCode(source, `ok`))
|
).toMatchObject(getPositionInCode(source, `ok`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`)),
|
||||||
).toMatchObject(getPositionInCode(source, `ok`, true))
|
).toMatchObject(getPositionInCode(source, `ok`, true))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
consumer.originalPositionFor(getPositionInCode(code, `list`)),
|
||||||
).toMatchObject(getPositionInCode(source, `list`))
|
).toMatchObject(getPositionInCode(source, `list`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
|
consumer.originalPositionFor(
|
||||||
|
getPositionInCode(code, `_ctx.list`, `list`),
|
||||||
|
),
|
||||||
).toMatchObject(getPositionInCode(source, `list`, true))
|
).toMatchObject(getPositionInCode(source, `list`, true))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
consumer.originalPositionFor(getPositionInCode(code, `value`)),
|
||||||
).toMatchObject(getPositionInCode(source, `value`))
|
).toMatchObject(getPositionInCode(source, `value`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
consumer.originalPositionFor(getPositionInCode(code, `index`)),
|
||||||
).toMatchObject(getPositionInCode(source, `index`))
|
).toMatchObject(getPositionInCode(source, `index`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
consumer.originalPositionFor(getPositionInCode(code, `value + index`)),
|
||||||
).toMatchObject(getPositionInCode(source, `value + index`))
|
).toMatchObject(getPositionInCode(source, `value + index`))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -188,7 +190,7 @@ describe('compiler: integration tests', () => {
|
||||||
const { code, map } = compile(source, {
|
const { code, map } = compile(source, {
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
sourceMap: true,
|
sourceMap: true,
|
||||||
filename: `foo.vue`
|
filename: `foo.vue`,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -198,64 +200,66 @@ describe('compiler: integration tests', () => {
|
||||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
consumer.originalPositionFor(getPositionInCode(code, `id`)),
|
||||||
).toMatchObject(getPositionInCode(source, `id`))
|
).toMatchObject(getPositionInCode(source, `id`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
consumer.originalPositionFor(getPositionInCode(code, `"foo"`)),
|
||||||
).toMatchObject(getPositionInCode(source, `"foo"`))
|
).toMatchObject(getPositionInCode(source, `"foo"`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
consumer.originalPositionFor(getPositionInCode(code, `class:`)),
|
||||||
).toMatchObject(getPositionInCode(source, `class=`))
|
).toMatchObject(getPositionInCode(source, `class=`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
consumer.originalPositionFor(getPositionInCode(code, `bar`)),
|
||||||
).toMatchObject(getPositionInCode(source, `bar`))
|
).toMatchObject(getPositionInCode(source, `bar`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`)),
|
||||||
).toMatchObject(getPositionInCode(source, `bar`, true))
|
).toMatchObject(getPositionInCode(source, `bar`, true))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
consumer.originalPositionFor(getPositionInCode(code, `baz`)),
|
||||||
).toMatchObject(getPositionInCode(source, `baz`))
|
).toMatchObject(getPositionInCode(source, `baz`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
|
consumer.originalPositionFor(getPositionInCode(code, `world`, true)),
|
||||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(
|
consumer.originalPositionFor(
|
||||||
getPositionInCode(code, `_ctx.world`, `world`)
|
getPositionInCode(code, `_ctx.world`, `world`),
|
||||||
)
|
),
|
||||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
consumer.originalPositionFor(getPositionInCode(code, `burn()`)),
|
||||||
).toMatchObject(getPositionInCode(source, `burn()`))
|
).toMatchObject(getPositionInCode(source, `burn()`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
consumer.originalPositionFor(getPositionInCode(code, `ok`)),
|
||||||
).toMatchObject(getPositionInCode(source, `ok`))
|
).toMatchObject(getPositionInCode(source, `ok`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
|
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`)),
|
||||||
).toMatchObject(getPositionInCode(source, `ok`, true))
|
).toMatchObject(getPositionInCode(source, `ok`, true))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
consumer.originalPositionFor(getPositionInCode(code, `list`)),
|
||||||
).toMatchObject(getPositionInCode(source, `list`))
|
).toMatchObject(getPositionInCode(source, `list`))
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
|
consumer.originalPositionFor(
|
||||||
|
getPositionInCode(code, `_ctx.list`, `list`),
|
||||||
|
),
|
||||||
).toMatchObject(getPositionInCode(source, `list`, true))
|
).toMatchObject(getPositionInCode(source, `list`, true))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
consumer.originalPositionFor(getPositionInCode(code, `value`)),
|
||||||
).toMatchObject(getPositionInCode(source, `value`))
|
).toMatchObject(getPositionInCode(source, `value`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
consumer.originalPositionFor(getPositionInCode(code, `index`)),
|
||||||
).toMatchObject(getPositionInCode(source, `index`))
|
).toMatchObject(getPositionInCode(source, `index`))
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
consumer.originalPositionFor(getPositionInCode(code, `value + index`)),
|
||||||
).toMatchObject(getPositionInCode(source, `value + index`))
|
).toMatchObject(getPositionInCode(source, `value + index`))
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,5 @@
|
||||||
import { baseCompile } from '../src/compile'
|
import { baseCompile } from '../src/compile'
|
||||||
import { PUSH_SCOPE_ID, POP_SCOPE_ID } from '../src/runtimeHelpers'
|
import { POP_SCOPE_ID, PUSH_SCOPE_ID } from '../src/runtimeHelpers'
|
||||||
import { PatchFlags } from '@vue/shared'
|
import { PatchFlags } from '@vue/shared'
|
||||||
import { genFlagText } from './testUtils'
|
import { genFlagText } from './testUtils'
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ describe('scopeId compiler support', () => {
|
||||||
test('should wrap default slot', () => {
|
test('should wrap default slot', () => {
|
||||||
const { code } = baseCompile(`<Child><div/></Child>`, {
|
const { code } = baseCompile(`<Child><div/></Child>`, {
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
scopeId: 'test'
|
scopeId: 'test',
|
||||||
})
|
})
|
||||||
expect(code).toMatch(`default: _withCtx(() => [`)
|
expect(code).toMatch(`default: _withCtx(() => [`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -33,8 +33,8 @@ describe('scopeId compiler support', () => {
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
scopeId: 'test'
|
scopeId: 'test',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`foo: _withCtx(({ msg }) => [`)
|
expect(code).toMatch(`foo: _withCtx(({ msg }) => [`)
|
||||||
expect(code).toMatch(`bar: _withCtx(() => [`)
|
expect(code).toMatch(`bar: _withCtx(() => [`)
|
||||||
|
@ -50,8 +50,8 @@ describe('scopeId compiler support', () => {
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
scopeId: 'test'
|
scopeId: 'test',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(/name: "foo",\s+fn: _withCtx\(/)
|
expect(code).toMatch(/name: "foo",\s+fn: _withCtx\(/)
|
||||||
expect(code).toMatch(/name: i,\s+fn: _withCtx\(/)
|
expect(code).toMatch(/name: i,\s+fn: _withCtx\(/)
|
||||||
|
@ -64,8 +64,8 @@ describe('scopeId compiler support', () => {
|
||||||
{
|
{
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
scopeId: 'test',
|
scopeId: 'test',
|
||||||
hoistStatic: true
|
hoistStatic: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(ast.helpers).toContain(PUSH_SCOPE_ID)
|
expect(ast.helpers).toContain(PUSH_SCOPE_ID)
|
||||||
expect(ast.helpers).toContain(POP_SCOPE_ID)
|
expect(ast.helpers).toContain(POP_SCOPE_ID)
|
||||||
|
@ -73,11 +73,11 @@ describe('scopeId compiler support', () => {
|
||||||
;[
|
;[
|
||||||
`const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n)`,
|
`const _withScopeId = n => (_pushScopeId("test"),n=n(),_popScopeId(),n)`,
|
||||||
`const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText(
|
`const _hoisted_1 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "hello", ${genFlagText(
|
||||||
PatchFlags.HOISTED
|
PatchFlags.HOISTED,
|
||||||
)}))`,
|
)}))`,
|
||||||
`const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText(
|
`const _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode("div", null, "world", ${genFlagText(
|
||||||
PatchFlags.HOISTED
|
PatchFlags.HOISTED,
|
||||||
)}))`
|
)}))`,
|
||||||
].forEach(c => expect(code).toMatch(c))
|
].forEach(c => expect(code).toMatch(c))
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import {
|
import {
|
||||||
NodeTypes,
|
type ElementNode,
|
||||||
ElementNode,
|
|
||||||
locStub,
|
|
||||||
Namespaces,
|
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
VNodeCall
|
Namespaces,
|
||||||
|
NodeTypes,
|
||||||
|
type VNodeCall,
|
||||||
|
locStub,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import {
|
import {
|
||||||
isString,
|
|
||||||
PatchFlags,
|
|
||||||
PatchFlagNames,
|
PatchFlagNames,
|
||||||
|
type PatchFlags,
|
||||||
|
type ShapeFlags,
|
||||||
isArray,
|
isArray,
|
||||||
ShapeFlags
|
isString,
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
|
|
||||||
const leadingBracketRE = /^\[/
|
const leadingBracketRE = /^\[/
|
||||||
|
@ -30,16 +30,16 @@ export function createObjectMatcher(obj: Record<string, any>) {
|
||||||
key: {
|
key: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: key.replace(bracketsRE, ''),
|
content: key.replace(bracketsRE, ''),
|
||||||
isStatic: !leadingBracketRE.test(key)
|
isStatic: !leadingBracketRE.test(key),
|
||||||
},
|
},
|
||||||
value: isString(obj[key])
|
value: isString(obj[key])
|
||||||
? {
|
? {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: obj[key].replace(bracketsRE, ''),
|
content: obj[key].replace(bracketsRE, ''),
|
||||||
isStatic: !leadingBracketRE.test(obj[key])
|
isStatic: !leadingBracketRE.test(obj[key]),
|
||||||
}
|
}
|
||||||
: obj[key]
|
: obj[key],
|
||||||
}))
|
})),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ export function createElementWithCodegen(
|
||||||
props?: VNodeCall['props'],
|
props?: VNodeCall['props'],
|
||||||
children?: VNodeCall['children'],
|
children?: VNodeCall['children'],
|
||||||
patchFlag?: VNodeCall['patchFlag'],
|
patchFlag?: VNodeCall['patchFlag'],
|
||||||
dynamicProps?: VNodeCall['dynamicProps']
|
dynamicProps?: VNodeCall['dynamicProps'],
|
||||||
): ElementNode {
|
): ElementNode {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
|
@ -69,15 +69,15 @@ export function createElementWithCodegen(
|
||||||
isBlock: false,
|
isBlock: false,
|
||||||
disableTracking: false,
|
disableTracking: false,
|
||||||
isComponent: false,
|
isComponent: false,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Flags = PatchFlags | ShapeFlags
|
type Flags = PatchFlags | ShapeFlags
|
||||||
export function genFlagText(
|
export function genFlagText(
|
||||||
flag: Flags | Flags[],
|
flag: Flags | Flags[],
|
||||||
names: { [k: number]: string } = PatchFlagNames
|
names: { [k: number]: string } = PatchFlagNames,
|
||||||
) {
|
) {
|
||||||
if (isArray(flag)) {
|
if (isArray(flag)) {
|
||||||
let f = 0
|
let f = 0
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import { baseParse } from '../src/parser'
|
import { baseParse } from '../src/parser'
|
||||||
import { transform, NodeTransform } from '../src/transform'
|
import { type NodeTransform, transform } from '../src/transform'
|
||||||
import {
|
import {
|
||||||
ElementNode,
|
type DirectiveNode,
|
||||||
|
type ElementNode,
|
||||||
|
type ExpressionNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
DirectiveNode,
|
type VNodeCall,
|
||||||
ExpressionNode,
|
|
||||||
VNodeCall
|
|
||||||
} from '../src/ast'
|
} from '../src/ast'
|
||||||
import { ErrorCodes, createCompilerError } from '../src/errors'
|
import { ErrorCodes, createCompilerError } from '../src/errors'
|
||||||
import {
|
import {
|
||||||
TO_DISPLAY_STRING,
|
CREATE_COMMENT,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
RENDER_SLOT,
|
RENDER_SLOT,
|
||||||
CREATE_COMMENT
|
TO_DISPLAY_STRING,
|
||||||
} from '../src/runtimeHelpers'
|
} from '../src/runtimeHelpers'
|
||||||
import { transformIf } from '../src/transforms/vIf'
|
import { transformIf } from '../src/transforms/vIf'
|
||||||
import { transformFor } from '../src/transforms/vFor'
|
import { transformFor } from '../src/transforms/vFor'
|
||||||
|
@ -34,7 +34,7 @@ describe('compiler: transform', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [plugin]
|
nodeTransforms: [plugin],
|
||||||
})
|
})
|
||||||
|
|
||||||
const div = ast.children[0] as ElementNode
|
const div = ast.children[0] as ElementNode
|
||||||
|
@ -43,29 +43,29 @@ describe('compiler: transform', () => {
|
||||||
ast,
|
ast,
|
||||||
{
|
{
|
||||||
parent: null,
|
parent: null,
|
||||||
currentNode: ast
|
currentNode: ast,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(calls[1]).toMatchObject([
|
expect(calls[1]).toMatchObject([
|
||||||
div,
|
div,
|
||||||
{
|
{
|
||||||
parent: ast,
|
parent: ast,
|
||||||
currentNode: div
|
currentNode: div,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(calls[2]).toMatchObject([
|
expect(calls[2]).toMatchObject([
|
||||||
div.children[0],
|
div.children[0],
|
||||||
{
|
{
|
||||||
parent: div,
|
parent: div,
|
||||||
currentNode: div.children[0]
|
currentNode: div.children[0],
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(calls[3]).toMatchObject([
|
expect(calls[3]).toMatchObject([
|
||||||
div.children[1],
|
div.children[1],
|
||||||
{
|
{
|
||||||
parent: div,
|
parent: div,
|
||||||
currentNode: div.children[1]
|
currentNode: div.children[1],
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -81,16 +81,16 @@ describe('compiler: transform', () => {
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: 'hello',
|
content: 'hello',
|
||||||
isEmpty: false
|
isEmpty: false,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const spy = vi.fn(plugin)
|
const spy = vi.fn(plugin)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [spy]
|
nodeTransforms: [spy],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ast.children.length).toBe(2)
|
expect(ast.children.length).toBe(2)
|
||||||
|
@ -115,7 +115,7 @@ describe('compiler: transform', () => {
|
||||||
}
|
}
|
||||||
const spy = vi.fn(plugin)
|
const spy = vi.fn(plugin)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [spy]
|
nodeTransforms: [spy],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ast.children.length).toBe(2)
|
expect(ast.children.length).toBe(2)
|
||||||
|
@ -143,7 +143,7 @@ describe('compiler: transform', () => {
|
||||||
}
|
}
|
||||||
const spy = vi.fn(plugin)
|
const spy = vi.fn(plugin)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [spy]
|
nodeTransforms: [spy],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ast.children.length).toBe(1)
|
expect(ast.children.length).toBe(1)
|
||||||
|
@ -170,7 +170,7 @@ describe('compiler: transform', () => {
|
||||||
}
|
}
|
||||||
const spy = vi.fn(plugin)
|
const spy = vi.fn(plugin)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [spy]
|
nodeTransforms: [spy],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ast.children.length).toBe(1)
|
expect(ast.children.length).toBe(1)
|
||||||
|
@ -194,7 +194,7 @@ describe('compiler: transform', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [mock]
|
nodeTransforms: [mock],
|
||||||
})
|
})
|
||||||
expect(ast.hoists).toMatchObject(hoisted)
|
expect(ast.hoists).toMatchObject(hoisted)
|
||||||
expect((ast as any).children[0].props[0].exp.content).toBe(`_hoisted_1`)
|
expect((ast as any).children[0].props[0].exp.content).toBe(`_hoisted_1`)
|
||||||
|
@ -211,13 +211,13 @@ describe('compiler: transform', () => {
|
||||||
|
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
filename: '/the/fileName.vue',
|
filename: '/the/fileName.vue',
|
||||||
nodeTransforms: [plugin]
|
nodeTransforms: [plugin],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(calls.length).toBe(2)
|
expect(calls.length).toBe(2)
|
||||||
expect(calls[1]).toMatchObject({
|
expect(calls[1]).toMatchObject({
|
||||||
filename: '/the/fileName.vue',
|
filename: '/the/fileName.vue',
|
||||||
selfName: 'FileName'
|
selfName: 'FileName',
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -226,19 +226,19 @@ describe('compiler: transform', () => {
|
||||||
const loc = ast.children[0].loc
|
const loc = ast.children[0].loc
|
||||||
const plugin: NodeTransform = (node, context) => {
|
const plugin: NodeTransform = (node, context) => {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_INVALID_END_TAG, node.loc)
|
createCompilerError(ErrorCodes.X_INVALID_END_TAG, node.loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const spy = vi.fn()
|
const spy = vi.fn()
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [plugin],
|
nodeTransforms: [plugin],
|
||||||
onError: spy
|
onError: spy,
|
||||||
})
|
})
|
||||||
expect(spy.mock.calls[0]).toMatchObject([
|
expect(spy.mock.calls[0]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_INVALID_END_TAG,
|
code: ErrorCodes.X_INVALID_END_TAG,
|
||||||
loc
|
loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -263,8 +263,8 @@ describe('compiler: transform', () => {
|
||||||
transformFor,
|
transformFor,
|
||||||
transformText,
|
transformText,
|
||||||
transformSlotOutlet,
|
transformSlotOutlet,
|
||||||
transformElement
|
transformElement,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -273,7 +273,7 @@ describe('compiler: transform', () => {
|
||||||
tag: VNodeCall['tag'],
|
tag: VNodeCall['tag'],
|
||||||
props?: VNodeCall['props'],
|
props?: VNodeCall['props'],
|
||||||
children?: VNodeCall['children'],
|
children?: VNodeCall['children'],
|
||||||
patchFlag?: VNodeCall['patchFlag']
|
patchFlag?: VNodeCall['patchFlag'],
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
|
@ -281,7 +281,7 @@ describe('compiler: transform', () => {
|
||||||
tag,
|
tag,
|
||||||
props,
|
props,
|
||||||
children,
|
children,
|
||||||
patchFlag
|
patchFlag,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -295,8 +295,8 @@ describe('compiler: transform', () => {
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT
|
callee: RENDER_SLOT,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -308,14 +308,14 @@ describe('compiler: transform', () => {
|
||||||
test('root v-if', () => {
|
test('root v-if', () => {
|
||||||
const ast = transformWithCodegen(`<div v-if="ok" />`)
|
const ast = transformWithCodegen(`<div v-if="ok" />`)
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
type: NodeTypes.IF
|
type: NodeTypes.IF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('root v-for', () => {
|
test('root v-for', () => {
|
||||||
const ast = transformWithCodegen(`<div v-for="i in list" />`)
|
const ast = transformWithCodegen(`<div v-for="i in list" />`)
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
type: NodeTypes.FOR
|
type: NodeTypes.FOR,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -323,28 +323,28 @@ describe('compiler: transform', () => {
|
||||||
const ast = transformWithCodegen(`<div v-foo/>`)
|
const ast = transformWithCodegen(`<div v-foo/>`)
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION }
|
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('single text', () => {
|
test('single text', () => {
|
||||||
const ast = transformWithCodegen(`hello`)
|
const ast = transformWithCodegen(`hello`)
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
type: NodeTypes.TEXT
|
type: NodeTypes.TEXT,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('single interpolation', () => {
|
test('single interpolation', () => {
|
||||||
const ast = transformWithCodegen(`{{ foo }}`)
|
const ast = transformWithCodegen(`{{ foo }}`)
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
type: NodeTypes.INTERPOLATION
|
type: NodeTypes.INTERPOLATION,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('single CompoundExpression', () => {
|
test('single CompoundExpression', () => {
|
||||||
const ast = transformWithCodegen(`{{ foo }} bar baz`)
|
const ast = transformWithCodegen(`{{ foo }} bar baz`)
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -356,10 +356,10 @@ describe('compiler: transform', () => {
|
||||||
undefined,
|
undefined,
|
||||||
[
|
[
|
||||||
{ type: NodeTypes.ELEMENT, tag: `div` },
|
{ type: NodeTypes.ELEMENT, tag: `div` },
|
||||||
{ type: NodeTypes.ELEMENT, tag: `div` }
|
{ type: NodeTypes.ELEMENT, tag: `div` },
|
||||||
] as any,
|
] as any,
|
||||||
genFlagText(PatchFlags.STABLE_FRAGMENT)
|
genFlagText(PatchFlags.STABLE_FRAGMENT),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -372,13 +372,13 @@ describe('compiler: transform', () => {
|
||||||
[
|
[
|
||||||
{ type: NodeTypes.COMMENT },
|
{ type: NodeTypes.COMMENT },
|
||||||
{ type: NodeTypes.ELEMENT, tag: `div` },
|
{ type: NodeTypes.ELEMENT, tag: `div` },
|
||||||
{ type: NodeTypes.COMMENT }
|
{ type: NodeTypes.COMMENT },
|
||||||
] as any,
|
] as any,
|
||||||
genFlagText([
|
genFlagText([
|
||||||
PatchFlags.STABLE_FRAGMENT,
|
PatchFlags.STABLE_FRAGMENT,
|
||||||
PatchFlags.DEV_ROOT_FRAGMENT
|
PatchFlags.DEV_ROOT_FRAGMENT,
|
||||||
])
|
]),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
import {
|
import {
|
||||||
|
type CompilerOptions,
|
||||||
|
ConstantTypes,
|
||||||
|
type ElementNode,
|
||||||
|
type ForNode,
|
||||||
|
type IfNode,
|
||||||
|
NodeTypes,
|
||||||
|
type VNodeCall,
|
||||||
|
generate,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
NodeTypes,
|
|
||||||
generate,
|
|
||||||
CompilerOptions,
|
|
||||||
VNodeCall,
|
|
||||||
IfNode,
|
|
||||||
ElementNode,
|
|
||||||
ForNode,
|
|
||||||
ConstantTypes
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import {
|
import {
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
|
NORMALIZE_CLASS,
|
||||||
RENDER_LIST,
|
RENDER_LIST,
|
||||||
NORMALIZE_CLASS
|
|
||||||
} from '../../src/runtimeHelpers'
|
} from '../../src/runtimeHelpers'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
|
@ -31,9 +31,9 @@ const hoistedChildrenArrayMatcher = (startIndex = 1, length = 1) => ({
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_hoisted_${startIndex + i}`
|
content: `_hoisted_${startIndex + i}`,
|
||||||
}
|
},
|
||||||
}))
|
})),
|
||||||
})
|
})
|
||||||
|
|
||||||
function transformWithHoist(template: string, options: CompilerOptions = {}) {
|
function transformWithHoist(template: string, options: CompilerOptions = {}) {
|
||||||
|
@ -45,17 +45,17 @@ function transformWithHoist(template: string, options: CompilerOptions = {}) {
|
||||||
transformFor,
|
transformFor,
|
||||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||||
transformElement,
|
transformElement,
|
||||||
transformText
|
transformText,
|
||||||
],
|
],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
on: transformOn,
|
on: transformOn,
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
expect(ast.codegenNode).toMatchObject({
|
expect(ast.codegenNode).toMatchObject({
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
isBlock: true
|
isBlock: true,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -67,14 +67,14 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
const root = transformWithHoist(`<div/>`)
|
const root = transformWithHoist(`<div/>`)
|
||||||
expect(root.hoists.length).toBe(0)
|
expect(root.hoists.length).toBe(0)
|
||||||
expect(root.codegenNode).toMatchObject({
|
expect(root.codegenNode).toMatchObject({
|
||||||
tag: `"div"`
|
tag: `"div"`,
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('hoist simple element', () => {
|
test('hoist simple element', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><span class="inline">hello</span></div>`
|
`<div><span class="inline">hello</span></div>`,
|
||||||
)
|
)
|
||||||
expect(root.hoists).toMatchObject([
|
expect(root.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
|
@ -83,15 +83,15 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
props: createObjectMatcher({ class: 'inline' }),
|
props: createObjectMatcher({ class: 'inline' }),
|
||||||
children: {
|
children: {
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `hello`
|
content: `hello`,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher()
|
},
|
||||||
|
hoistedChildrenArrayMatcher(),
|
||||||
])
|
])
|
||||||
expect(root.codegenNode).toMatchObject({
|
expect(root.codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: { content: `_hoisted_2` }
|
children: { content: `_hoisted_2` },
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -105,13 +105,13 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: [
|
children: [
|
||||||
{ type: NodeTypes.ELEMENT, tag: `span` },
|
{ type: NodeTypes.ELEMENT, tag: `span` },
|
||||||
{ type: NodeTypes.ELEMENT, tag: `span` }
|
{ type: NodeTypes.ELEMENT, tag: `span` },
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher()
|
hoistedChildrenArrayMatcher(),
|
||||||
])
|
])
|
||||||
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
||||||
content: '_hoisted_2'
|
content: '_hoisted_2',
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -123,12 +123,12 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: [{ type: NodeTypes.COMMENT, content: `comment` }]
|
children: [{ type: NodeTypes.COMMENT, content: `comment` }],
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher()
|
hoistedChildrenArrayMatcher(),
|
||||||
])
|
])
|
||||||
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
||||||
content: `_hoisted_2`
|
content: `_hoisted_2`,
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -138,16 +138,16 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
expect(root.hoists).toMatchObject([
|
expect(root.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"span"`
|
tag: `"span"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`
|
tag: `"div"`,
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher(1, 2)
|
hoistedChildrenArrayMatcher(1, 2),
|
||||||
])
|
])
|
||||||
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
||||||
content: '_hoisted_3'
|
content: '_hoisted_3',
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -160,9 +160,9 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `_component_Comp`
|
tag: `_component_Comp`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -177,17 +177,17 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
id: `[foo]`
|
id: `[foo]`,
|
||||||
}),
|
}),
|
||||||
children: undefined,
|
children: undefined,
|
||||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||||
dynamicProps: {
|
dynamicProps: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_hoisted_1`,
|
content: `_hoisted_1`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -199,14 +199,14 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: 'foo' })
|
props: createObjectMatcher({ key: 'foo' }),
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher()
|
hoistedChildrenArrayMatcher(),
|
||||||
])
|
])
|
||||||
expect(root.codegenNode).toMatchObject({
|
expect(root.codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: { content: `_hoisted_2` }
|
children: { content: `_hoisted_2` },
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -221,10 +221,10 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
key: `[foo]`
|
key: `[foo]`,
|
||||||
})
|
}),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -239,12 +239,12 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
ref: `[foo]`
|
ref: `[foo]`,
|
||||||
}),
|
}),
|
||||||
children: undefined,
|
children: undefined,
|
||||||
patchFlag: genFlagText(PatchFlags.NEED_PATCH)
|
patchFlag: genFlagText(PatchFlags.NEED_PATCH),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -260,22 +260,22 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: {
|
props: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_hoisted_1`
|
content: `_hoisted_1`,
|
||||||
},
|
},
|
||||||
children: undefined,
|
children: undefined,
|
||||||
patchFlag: genFlagText(PatchFlags.NEED_PATCH),
|
patchFlag: genFlagText(PatchFlags.NEED_PATCH),
|
||||||
directives: {
|
directives: {
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('hoist static props for elements with dynamic text children', () => {
|
test('hoist static props for elements with dynamic text children', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><div id="foo">{{ hello }}</div></div>`
|
`<div><div id="foo">{{ hello }}</div></div>`,
|
||||||
)
|
)
|
||||||
expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'foo' })])
|
expect(root.hoists).toMatchObject([createObjectMatcher({ id: 'foo' })])
|
||||||
expect((root.codegenNode as VNodeCall).children).toMatchObject([
|
expect((root.codegenNode as VNodeCall).children).toMatchObject([
|
||||||
|
@ -286,9 +286,9 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: { content: `_hoisted_1` },
|
props: { content: `_hoisted_1` },
|
||||||
children: { type: NodeTypes.INTERPOLATION },
|
children: { type: NodeTypes.INTERPOLATION },
|
||||||
patchFlag: genFlagText(PatchFlags.TEXT)
|
patchFlag: genFlagText(PatchFlags.TEXT),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -303,30 +303,30 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: { content: `_hoisted_1` },
|
props: { content: `_hoisted_1` },
|
||||||
children: [{ type: NodeTypes.ELEMENT, tag: `Comp` }]
|
children: [{ type: NodeTypes.ELEMENT, tag: `Comp` }],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should hoist v-if props/children if static', () => {
|
test('should hoist v-if props/children if static', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><div v-if="ok" id="foo"><span/></div></div>`
|
`<div><div v-if="ok" id="foo"><span/></div></div>`,
|
||||||
)
|
)
|
||||||
expect(root.hoists).toMatchObject([
|
expect(root.hoists).toMatchObject([
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
key: `[0]`, // key injected by v-if branch
|
key: `[0]`, // key injected by v-if branch
|
||||||
id: 'foo'
|
id: 'foo',
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"span"`
|
tag: `"span"`,
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher(2)
|
hoistedChildrenArrayMatcher(2),
|
||||||
])
|
])
|
||||||
expect(
|
expect(
|
||||||
((root.children[0] as ElementNode).children[0] as IfNode).codegenNode
|
((root.children[0] as ElementNode).children[0] as IfNode).codegenNode,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
consequent: {
|
consequent: {
|
||||||
|
@ -334,25 +334,25 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: { content: `_hoisted_1` },
|
props: { content: `_hoisted_1` },
|
||||||
children: { content: `_hoisted_3` }
|
children: { content: `_hoisted_3` },
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should hoist v-for children if static', () => {
|
test('should hoist v-for children if static', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><div v-for="i in list" id="foo"><span/></div></div>`
|
`<div><div v-for="i in list" id="foo"><span/></div></div>`,
|
||||||
)
|
)
|
||||||
expect(root.hoists).toMatchObject([
|
expect(root.hoists).toMatchObject([
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
id: 'foo'
|
id: 'foo',
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"span"`
|
tag: `"span"`,
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher(2)
|
hoistedChildrenArrayMatcher(2),
|
||||||
])
|
])
|
||||||
const forBlockCodegen = (
|
const forBlockCodegen = (
|
||||||
(root.children[0] as ElementNode).children[0] as ForNode
|
(root.children[0] as ElementNode).children[0] as ForNode
|
||||||
|
@ -363,16 +363,16 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: {
|
children: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_LIST
|
callee: RENDER_LIST,
|
||||||
},
|
},
|
||||||
patchFlag: genFlagText(PatchFlags.UNKEYED_FRAGMENT)
|
patchFlag: genFlagText(PatchFlags.UNKEYED_FRAGMENT),
|
||||||
})
|
})
|
||||||
const innerBlockCodegen = forBlockCodegen!.children.arguments[1]
|
const innerBlockCodegen = forBlockCodegen!.children.arguments[1]
|
||||||
expect(innerBlockCodegen.returns).toMatchObject({
|
expect(innerBlockCodegen.returns).toMatchObject({
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: { content: `_hoisted_1` },
|
props: { content: `_hoisted_1` },
|
||||||
children: { content: `_hoisted_3` }
|
children: { content: `_hoisted_3` },
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -382,8 +382,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><span>foo {{ 1 }} {{ true }}</span></div>`,
|
`<div><span>foo {{ 1 }} {{ true }}</span></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(root.hoists).toMatchObject([
|
expect(root.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
|
@ -391,18 +391,18 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
tag: `"span"`,
|
tag: `"span"`,
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: {
|
children: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher()
|
},
|
||||||
|
hoistedChildrenArrayMatcher(),
|
||||||
])
|
])
|
||||||
expect(root.codegenNode).toMatchObject({
|
expect(root.codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: {
|
children: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_hoisted_2`
|
content: `_hoisted_2`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -411,8 +411,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><span :foo="0">{{ 1 }}</span></div>`,
|
`<div><span :foo="0">{{ 1 }}</span></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(root.hoists).toMatchObject([
|
expect(root.hoists).toMatchObject([
|
||||||
|
@ -425,19 +425,19 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
content: {
|
content: {
|
||||||
content: `1`,
|
content: `1`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
constType: ConstantTypes.CAN_STRINGIFY
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
hoistedChildrenArrayMatcher()
|
},
|
||||||
|
},
|
||||||
|
hoistedChildrenArrayMatcher(),
|
||||||
])
|
])
|
||||||
expect(root.codegenNode).toMatchObject({
|
expect(root.codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: undefined,
|
props: undefined,
|
||||||
children: {
|
children: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_hoisted_2`
|
content: `_hoisted_2`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -446,8 +446,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><span :class="{ foo: true }">{{ bar }}</span></div>`,
|
`<div><span :class="{ foo: true }">{{ bar }}</span></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(root.hoists).toMatchObject([
|
expect(root.hoists).toMatchObject([
|
||||||
|
@ -458,7 +458,7 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
key: {
|
key: {
|
||||||
content: `class`,
|
content: `class`,
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
constType: ConstantTypes.CAN_STRINGIFY
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
@ -467,13 +467,13 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
{
|
{
|
||||||
content: `{ foo: true }`,
|
content: `{ foo: true }`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
constType: ConstantTypes.CAN_STRINGIFY
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(root.codegenNode).toMatchObject({
|
expect(root.codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
|
@ -486,20 +486,20 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
tag: `"span"`,
|
tag: `"span"`,
|
||||||
props: {
|
props: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_hoisted_1`
|
content: `_hoisted_1`,
|
||||||
},
|
},
|
||||||
children: {
|
children: {
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`,
|
content: `_ctx.bar`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
constType: ConstantTypes.NOT_CONSTANT
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
}
|
|
||||||
},
|
},
|
||||||
patchFlag: `1 /* TEXT */`
|
},
|
||||||
}
|
patchFlag: `1 /* TEXT */`,
|
||||||
}
|
},
|
||||||
]
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -508,8 +508,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><p v-for="o in list"><span>{{ o }}</span></p></div>`,
|
`<div><p v-for="o in list"><span>{{ o }}</span></p></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(root.hoists.length).toBe(0)
|
expect(root.hoists.length).toBe(0)
|
||||||
|
@ -520,8 +520,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><p v-for="o in list"><span>{{ o + 'foo' }}</span></p></div>`,
|
`<div><p v-for="o in list"><span>{{ o + 'foo' }}</span></p></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(root.hoists.length).toBe(0)
|
expect(root.hoists.length).toBe(0)
|
||||||
|
@ -532,8 +532,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<Comp v-slot="{ foo }">{{ foo }}</Comp>`,
|
`<Comp v-slot="{ foo }">{{ foo }}</Comp>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(root.hoists.length).toBe(0)
|
expect(root.hoists.length).toBe(0)
|
||||||
|
@ -545,8 +545,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
`<div><div><div @click="foo"/></div></div>`,
|
`<div><div><div @click="foo"/></div></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
|
@ -554,8 +554,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
expect(
|
expect(
|
||||||
generate(root, {
|
generate(root, {
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}).code
|
}).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -564,8 +564,8 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
`<div><div><div :class="{}" @click="foo"/></div></div>`,
|
`<div><div><div :class="{}" @click="foo"/></div></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
|
@ -573,14 +573,14 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
expect(
|
expect(
|
||||||
generate(root, {
|
generate(root, {
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}).code
|
}).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should NOT hoist keyed template v-for with plain element child', () => {
|
test('should NOT hoist keyed template v-for with plain element child', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><template v-for="item in items" :key="item"><span/></template></div>`
|
`<div><template v-for="item in items" :key="item"><span/></template></div>`,
|
||||||
)
|
)
|
||||||
expect(root.hoists.length).toBe(0)
|
expect(root.hoists.length).toBe(0)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -588,7 +588,7 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
|
|
||||||
test('should NOT hoist SVG with directives', () => {
|
test('should NOT hoist SVG with directives', () => {
|
||||||
const root = transformWithHoist(
|
const root = transformWithHoist(
|
||||||
`<div><svg v-foo><path d="M2,3H5.5L12"/></svg></div>`
|
`<div><svg v-foo><path d="M2,3H5.5L12"/></svg></div>`,
|
||||||
)
|
)
|
||||||
expect(root.hoists.length).toBe(2)
|
expect(root.hoists.length).toBe(2)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -596,13 +596,13 @@ describe('compiler: hoistStatic transform', () => {
|
||||||
|
|
||||||
test('clone hoisted array children in HMR mode', () => {
|
test('clone hoisted array children in HMR mode', () => {
|
||||||
const root = transformWithHoist(`<div><span class="hi"></span></div>`, {
|
const root = transformWithHoist(`<div><span class="hi"></span></div>`, {
|
||||||
hmr: true
|
hmr: true,
|
||||||
})
|
})
|
||||||
expect(root.hoists.length).toBe(2)
|
expect(root.hoists.length).toBe(2)
|
||||||
expect(root.codegenNode).toMatchObject({
|
expect(root.codegenNode).toMatchObject({
|
||||||
children: {
|
children: {
|
||||||
content: '[..._hoisted_2]'
|
content: '[..._hoisted_2]',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import {
|
import {
|
||||||
|
type ElementNode,
|
||||||
|
type VNodeCall,
|
||||||
|
noopDirectiveTransform,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
ElementNode,
|
|
||||||
noopDirectiveTransform,
|
|
||||||
VNodeCall
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@ describe('compiler: noop directive transform', () => {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformElement],
|
nodeTransforms: [transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
noop: noopDirectiveTransform
|
noop: noopDirectiveTransform,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const node = ast.children[0] as ElementNode
|
const node = ast.children[0] as ElementNode
|
||||||
// As v-noop adds no properties the codegen should be identical to
|
// As v-noop adds no properties the codegen should be identical to
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
|
BindingTypes,
|
||||||
|
type CompilerOptions,
|
||||||
|
ConstantTypes,
|
||||||
|
type DirectiveNode,
|
||||||
|
type ElementNode,
|
||||||
|
type InterpolationNode,
|
||||||
|
NodeTypes,
|
||||||
|
baseCompile,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
ElementNode,
|
|
||||||
DirectiveNode,
|
|
||||||
NodeTypes,
|
|
||||||
CompilerOptions,
|
|
||||||
InterpolationNode,
|
|
||||||
ConstantTypes,
|
|
||||||
BindingTypes,
|
|
||||||
baseCompile
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformIf } from '../../src/transforms/vIf'
|
import { transformIf } from '../../src/transforms/vIf'
|
||||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
|
@ -16,13 +16,13 @@ import { PatchFlagNames, PatchFlags } from '../../../shared/src'
|
||||||
|
|
||||||
function parseWithExpressionTransform(
|
function parseWithExpressionTransform(
|
||||||
template: string,
|
template: string,
|
||||||
options: CompilerOptions = {}
|
options: CompilerOptions = {},
|
||||||
) {
|
) {
|
||||||
const ast = parse(template, options)
|
const ast = parse(template, options)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
nodeTransforms: [transformIf, transformExpression],
|
nodeTransforms: [transformIf, transformExpression],
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast.children[0]
|
return ast.children[0]
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ describe('compiler: expression transform', () => {
|
||||||
const node = parseWithExpressionTransform(`{{ foo }}`) as InterpolationNode
|
const node = parseWithExpressionTransform(`{{ foo }}`) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.foo`
|
content: `_ctx.foo`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -40,34 +40,34 @@ describe('compiler: expression transform', () => {
|
||||||
const node = parseWithExpressionTransform(`{{}}`) as InterpolationNode
|
const node = parseWithExpressionTransform(`{{}}`) as InterpolationNode
|
||||||
const node2 = parseWithExpressionTransform(`{{ }}`) as InterpolationNode
|
const node2 = parseWithExpressionTransform(`{{ }}`) as InterpolationNode
|
||||||
const node3 = parseWithExpressionTransform(
|
const node3 = parseWithExpressionTransform(
|
||||||
`<div>{{ }}</div>`
|
`<div>{{ }}</div>`,
|
||||||
) as ElementNode
|
) as ElementNode
|
||||||
|
|
||||||
const objectToBeMatched = {
|
const objectToBeMatched = {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: ``
|
content: ``,
|
||||||
}
|
}
|
||||||
expect(node.content).toMatchObject(objectToBeMatched)
|
expect(node.content).toMatchObject(objectToBeMatched)
|
||||||
expect(node2.content).toMatchObject(objectToBeMatched)
|
expect(node2.content).toMatchObject(objectToBeMatched)
|
||||||
expect((node3.children[0] as InterpolationNode).content).toMatchObject(
|
expect((node3.children[0] as InterpolationNode).content).toMatchObject(
|
||||||
objectToBeMatched
|
objectToBeMatched,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('interpolation (children)', () => {
|
test('interpolation (children)', () => {
|
||||||
const el = parseWithExpressionTransform(
|
const el = parseWithExpressionTransform(
|
||||||
`<div>{{ foo }}</div>`
|
`<div>{{ foo }}</div>`,
|
||||||
) as ElementNode
|
) as ElementNode
|
||||||
const node = el.children[0] as InterpolationNode
|
const node = el.children[0] as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.foo`
|
content: `_ctx.foo`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('interpolation (complex)', () => {
|
test('interpolation (complex)', () => {
|
||||||
const el = parseWithExpressionTransform(
|
const el = parseWithExpressionTransform(
|
||||||
`<div>{{ foo + bar(baz.qux) }}</div>`
|
`<div>{{ foo + bar(baz.qux) }}</div>`,
|
||||||
) as ElementNode
|
) as ElementNode
|
||||||
const node = el.children[0] as InterpolationNode
|
const node = el.children[0] as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
|
@ -80,46 +80,46 @@ describe('compiler: expression transform', () => {
|
||||||
{ content: `_ctx.baz` },
|
{ content: `_ctx.baz` },
|
||||||
`.`,
|
`.`,
|
||||||
{ content: `qux` },
|
{ content: `qux` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('directive value', () => {
|
test('directive value', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`<div v-foo:arg="baz"/>`
|
`<div v-foo:arg="baz"/>`,
|
||||||
) as ElementNode
|
) as ElementNode
|
||||||
const arg = (node.props[0] as DirectiveNode).arg!
|
const arg = (node.props[0] as DirectiveNode).arg!
|
||||||
expect(arg).toMatchObject({
|
expect(arg).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `arg`
|
content: `arg`,
|
||||||
})
|
})
|
||||||
const exp = (node.props[0] as DirectiveNode).exp!
|
const exp = (node.props[0] as DirectiveNode).exp!
|
||||||
expect(exp).toMatchObject({
|
expect(exp).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.baz`
|
content: `_ctx.baz`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('dynamic directive arg', () => {
|
test('dynamic directive arg', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`<div v-foo:[arg]="baz"/>`
|
`<div v-foo:[arg]="baz"/>`,
|
||||||
) as ElementNode
|
) as ElementNode
|
||||||
const arg = (node.props[0] as DirectiveNode).arg!
|
const arg = (node.props[0] as DirectiveNode).arg!
|
||||||
expect(arg).toMatchObject({
|
expect(arg).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.arg`
|
content: `_ctx.arg`,
|
||||||
})
|
})
|
||||||
const exp = (node.props[0] as DirectiveNode).exp!
|
const exp = (node.props[0] as DirectiveNode).exp!
|
||||||
expect(exp).toMatchObject({
|
expect(exp).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.baz`
|
content: `_ctx.baz`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix complex expressions', () => {
|
test('should prefix complex expressions', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ foo(baz + 1, { key: kuz }) }}`
|
`{{ foo(baz + 1, { key: kuz }) }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
// should parse into compound expression
|
// should parse into compound expression
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
|
@ -129,56 +129,56 @@ describe('compiler: expression transform', () => {
|
||||||
content: `_ctx.foo`,
|
content: `_ctx.foo`,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 3, line: 1, column: 4 },
|
start: { offset: 3, line: 1, column: 4 },
|
||||||
end: { offset: 6, line: 1, column: 7 }
|
end: { offset: 6, line: 1, column: 7 },
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
`(`,
|
`(`,
|
||||||
{
|
{
|
||||||
content: `_ctx.baz`,
|
content: `_ctx.baz`,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 7, line: 1, column: 8 },
|
start: { offset: 7, line: 1, column: 8 },
|
||||||
end: { offset: 10, line: 1, column: 11 }
|
end: { offset: 10, line: 1, column: 11 },
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
` + 1, { key: `,
|
` + 1, { key: `,
|
||||||
{
|
{
|
||||||
content: `_ctx.kuz`,
|
content: `_ctx.kuz`,
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 23, line: 1, column: 24 },
|
start: { offset: 23, line: 1, column: 24 },
|
||||||
end: { offset: 26, line: 1, column: 27 }
|
end: { offset: 26, line: 1, column: 27 },
|
||||||
}
|
|
||||||
},
|
},
|
||||||
` })`
|
},
|
||||||
]
|
` })`,
|
||||||
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix whitelisted globals', () => {
|
test('should not prefix whitelisted globals', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ Math.max(1, 2) }}`
|
`{{ Math.max(1, 2) }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [{ content: `Math` }, `.`, { content: `max` }, `(1, 2)`]
|
children: [{ content: `Math` }, `.`, { content: `max` }, `(1, 2)`],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
(parseWithExpressionTransform(`{{ new Error() }}`) as InterpolationNode)
|
(parseWithExpressionTransform(`{{ new Error() }}`) as InterpolationNode)
|
||||||
.content
|
.content,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: ['new ', { content: 'Error' }, '()']
|
children: ['new ', { content: 'Error' }, '()'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix reserved literals', () => {
|
test('should not prefix reserved literals', () => {
|
||||||
function assert(exp: string) {
|
function assert(exp: string) {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ ${exp} }}`
|
`{{ ${exp} }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: exp
|
content: exp,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
assert(`true`)
|
assert(`true`)
|
||||||
|
@ -189,7 +189,7 @@ describe('compiler: expression transform', () => {
|
||||||
|
|
||||||
test('should not prefix id of a function declaration', () => {
|
test('should not prefix id of a function declaration', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ function foo() { return bar } }}`
|
`{{ function foo() { return bar } }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -198,14 +198,14 @@ describe('compiler: expression transform', () => {
|
||||||
{ content: `foo` },
|
{ content: `foo` },
|
||||||
`() { return `,
|
`() { return `,
|
||||||
{ content: `_ctx.bar` },
|
{ content: `_ctx.bar` },
|
||||||
` }`
|
` }`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix params of a function expression', () => {
|
test('should not prefix params of a function expression', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ foo => foo + bar }}`
|
`{{ foo => foo + bar }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -214,14 +214,14 @@ describe('compiler: expression transform', () => {
|
||||||
` => `,
|
` => `,
|
||||||
{ content: `foo` },
|
{ content: `foo` },
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `_ctx.bar` }
|
{ content: `_ctx.bar` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix default value of a function expression param', () => {
|
test('should prefix default value of a function expression param', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ (foo = baz) => foo + bar }}`
|
`{{ (foo = baz) => foo + bar }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -233,14 +233,14 @@ describe('compiler: expression transform', () => {
|
||||||
`) => `,
|
`) => `,
|
||||||
{ content: `foo` },
|
{ content: `foo` },
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `_ctx.bar` }
|
{ content: `_ctx.bar` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix function param destructuring', () => {
|
test('should not prefix function param destructuring', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ ({ foo }) => foo + bar }}`
|
`{{ ({ foo }) => foo + bar }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -250,14 +250,14 @@ describe('compiler: expression transform', () => {
|
||||||
` }) => `,
|
` }) => `,
|
||||||
{ content: `foo` },
|
{ content: `foo` },
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `_ctx.bar` }
|
{ content: `_ctx.bar` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('function params should not affect out of scope identifiers', () => {
|
test('function params should not affect out of scope identifiers', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ { a: foo => foo, b: foo } }}`
|
`{{ { a: foo => foo, b: foo } }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -268,14 +268,14 @@ describe('compiler: expression transform', () => {
|
||||||
{ content: `foo` },
|
{ content: `foo` },
|
||||||
`, b: `,
|
`, b: `,
|
||||||
{ content: `_ctx.foo` },
|
{ content: `_ctx.foo` },
|
||||||
` }`
|
` }`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix default value of function param destructuring', () => {
|
test('should prefix default value of function param destructuring', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ ({ foo = bar }) => foo + bar }}`
|
`{{ ({ foo = bar }) => foo + bar }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -287,13 +287,13 @@ describe('compiler: expression transform', () => {
|
||||||
` }) => `,
|
` }) => `,
|
||||||
{ content: `foo` },
|
{ content: `foo` },
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `_ctx.bar` }
|
{ content: `_ctx.bar` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
test('should not prefix an object property key', () => {
|
test('should not prefix an object property key', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ { foo() { baz() }, value: bar } }}`
|
`{{ { foo() { baz() }, value: bar } }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -302,24 +302,24 @@ describe('compiler: expression transform', () => {
|
||||||
{ content: `_ctx.baz` },
|
{ content: `_ctx.baz` },
|
||||||
`() }, value: `,
|
`() }, value: `,
|
||||||
{ content: `_ctx.bar` },
|
{ content: `_ctx.bar` },
|
||||||
` }`
|
` }`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not duplicate object key with same name as value', () => {
|
test('should not duplicate object key with same name as value', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ { foo: foo } }}`
|
`{{ { foo: foo } }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`]
|
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix a computed object property key', () => {
|
test('should prefix a computed object property key', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ { [foo]: bar } }}`
|
`{{ { [foo]: bar } }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -328,24 +328,24 @@ describe('compiler: expression transform', () => {
|
||||||
{ content: `_ctx.foo` },
|
{ content: `_ctx.foo` },
|
||||||
`]: `,
|
`]: `,
|
||||||
{ content: `_ctx.bar` },
|
{ content: `_ctx.bar` },
|
||||||
` }`
|
` }`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix object property shorthand value', () => {
|
test('should prefix object property shorthand value', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ { foo } }}`
|
`{{ { foo } }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`]
|
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix id in a member expression', () => {
|
test('should not prefix id in a member expression', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ foo.bar.baz }}`
|
`{{ foo.bar.baz }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -354,14 +354,14 @@ describe('compiler: expression transform', () => {
|
||||||
`.`,
|
`.`,
|
||||||
{ content: `bar` },
|
{ content: `bar` },
|
||||||
`.`,
|
`.`,
|
||||||
{ content: `baz` }
|
{ content: `baz` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix computed id in a member expression', () => {
|
test('should prefix computed id in a member expression', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ foo[bar][baz] }}`
|
`{{ foo[bar][baz] }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -371,8 +371,8 @@ describe('compiler: expression transform', () => {
|
||||||
{ content: `_ctx.bar` },
|
{ content: `_ctx.bar` },
|
||||||
`][`,
|
`][`,
|
||||||
{ content: '_ctx.baz' },
|
{ content: '_ctx.baz' },
|
||||||
`]`
|
`]`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -380,23 +380,23 @@ describe('compiler: expression transform', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
parseWithExpressionTransform(`{{ a( }}`, { onError })
|
parseWithExpressionTransform(`{{ a( }}`, { onError })
|
||||||
expect(onError.mock.calls[0][0].message).toMatch(
|
expect(onError.mock.calls[0][0].message).toMatch(
|
||||||
`Error parsing JavaScript expression: Unexpected token`
|
`Error parsing JavaScript expression: Unexpected token`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix in assignment', () => {
|
test('should prefix in assignment', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ x = 1 }}`
|
`{{ x = 1 }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [{ content: `_ctx.x` }, ` = 1`]
|
children: [{ content: `_ctx.x` }, ` = 1`],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix in assignment pattern', () => {
|
test('should prefix in assignment pattern', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ { x, y: [z] } = obj }}`
|
`{{ { x, y: [z] } = obj }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -406,47 +406,47 @@ describe('compiler: expression transform', () => {
|
||||||
`, y: [`,
|
`, y: [`,
|
||||||
{ content: `_ctx.z` },
|
{ content: `_ctx.z` },
|
||||||
`] } = `,
|
`] } = `,
|
||||||
{ content: `_ctx.obj` }
|
{ content: `_ctx.obj` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// #8295
|
// #8295
|
||||||
test('should treat floating point number literals as constant', () => {
|
test('should treat floating point number literals as constant', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ [1, 2.1] }}`
|
`{{ [1, 2.1] }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
constType: ConstantTypes.CAN_STRINGIFY
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('ES Proposals support', () => {
|
describe('ES Proposals support', () => {
|
||||||
test('bigInt', () => {
|
test('bigInt', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ 13000n }}`
|
`{{ 13000n }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `13000n`,
|
content: `13000n`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
constType: ConstantTypes.CAN_STRINGIFY
|
constType: ConstantTypes.CAN_STRINGIFY,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('nullish coalescing', () => {
|
test('nullish coalescing', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ a ?? b }}`
|
`{{ a ?? b }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [{ content: `_ctx.a` }, ` ?? `, { content: `_ctx.b` }]
|
children: [{ content: `_ctx.a` }, ` ?? `, { content: `_ctx.b` }],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('optional chaining', () => {
|
test('optional chaining', () => {
|
||||||
const node = parseWithExpressionTransform(
|
const node = parseWithExpressionTransform(
|
||||||
`{{ a?.b?.c }}`
|
`{{ a?.b?.c }}`,
|
||||||
) as InterpolationNode
|
) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -455,8 +455,8 @@ describe('compiler: expression transform', () => {
|
||||||
`?.`,
|
`?.`,
|
||||||
{ content: `b` },
|
{ content: `b` },
|
||||||
`?.`,
|
`?.`,
|
||||||
{ content: `c` }
|
{ content: `c` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -467,14 +467,18 @@ describe('compiler: expression transform', () => {
|
||||||
[
|
[
|
||||||
'pipelineOperator',
|
'pipelineOperator',
|
||||||
{
|
{
|
||||||
proposal: 'minimal'
|
proposal: 'minimal',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
]
|
],
|
||||||
}) as InterpolationNode
|
}) as InterpolationNode
|
||||||
expect(node.content).toMatchObject({
|
expect(node.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [{ content: `_ctx.a` }, ` |> `, { content: `_ctx.uppercase` }]
|
children: [
|
||||||
|
{ content: `_ctx.a` },
|
||||||
|
` |> `,
|
||||||
|
{ content: `_ctx.uppercase` },
|
||||||
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -488,23 +492,23 @@ describe('compiler: expression transform', () => {
|
||||||
options: BindingTypes.OPTIONS,
|
options: BindingTypes.OPTIONS,
|
||||||
reactive: BindingTypes.SETUP_REACTIVE_CONST,
|
reactive: BindingTypes.SETUP_REACTIVE_CONST,
|
||||||
literal: BindingTypes.LITERAL_CONST,
|
literal: BindingTypes.LITERAL_CONST,
|
||||||
isNaN: BindingTypes.SETUP_REF
|
isNaN: BindingTypes.SETUP_REF,
|
||||||
}
|
}
|
||||||
|
|
||||||
function compileWithBindingMetadata(
|
function compileWithBindingMetadata(
|
||||||
template: string,
|
template: string,
|
||||||
options?: CompilerOptions
|
options?: CompilerOptions,
|
||||||
) {
|
) {
|
||||||
return baseCompile(template, {
|
return baseCompile(template, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
bindingMetadata,
|
bindingMetadata,
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test('non-inline mode', () => {
|
test('non-inline mode', () => {
|
||||||
const { code } = compileWithBindingMetadata(
|
const { code } = compileWithBindingMetadata(
|
||||||
`<div>{{ props }} {{ setup }} {{ data }} {{ options }} {{ isNaN }}</div>`
|
`<div>{{ props }} {{ setup }} {{ data }} {{ options }} {{ isNaN }}</div>`,
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`$props.props`)
|
expect(code).toMatch(`$props.props`)
|
||||||
expect(code).toMatch(`$setup.setup`)
|
expect(code).toMatch(`$setup.setup`)
|
||||||
|
@ -521,7 +525,7 @@ describe('compiler: expression transform', () => {
|
||||||
for (const x in list) {
|
for (const x in list) {
|
||||||
log(x)
|
log(x)
|
||||||
}
|
}
|
||||||
}"/>`
|
}"/>`,
|
||||||
)
|
)
|
||||||
expect(code).not.toMatch(`_ctx.x`)
|
expect(code).not.toMatch(`_ctx.x`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -533,7 +537,7 @@ describe('compiler: expression transform', () => {
|
||||||
for (const x of list) {
|
for (const x of list) {
|
||||||
log(x)
|
log(x)
|
||||||
}
|
}
|
||||||
}"/>`
|
}"/>`,
|
||||||
)
|
)
|
||||||
expect(code).not.toMatch(`_ctx.x`)
|
expect(code).not.toMatch(`_ctx.x`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -545,7 +549,7 @@ describe('compiler: expression transform', () => {
|
||||||
for (let i = 0; i < list.length; i++) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
log(i)
|
log(i)
|
||||||
}
|
}
|
||||||
}"/>`
|
}"/>`,
|
||||||
)
|
)
|
||||||
expect(code).not.toMatch(`_ctx.i`)
|
expect(code).not.toMatch(`_ctx.i`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -554,7 +558,7 @@ describe('compiler: expression transform', () => {
|
||||||
test('inline mode', () => {
|
test('inline mode', () => {
|
||||||
const { code } = compileWithBindingMetadata(
|
const { code } = compileWithBindingMetadata(
|
||||||
`<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,
|
`<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,
|
||||||
{ inline: true }
|
{ inline: true },
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`__props.props`)
|
expect(code).toMatch(`__props.props`)
|
||||||
expect(code).toMatch(`_unref(setup)`)
|
expect(code).toMatch(`_unref(setup)`)
|
||||||
|
@ -567,12 +571,12 @@ describe('compiler: expression transform', () => {
|
||||||
|
|
||||||
test('literal const handling', () => {
|
test('literal const handling', () => {
|
||||||
const { code } = compileWithBindingMetadata(`<div>{{ literal }}</div>`, {
|
const { code } = compileWithBindingMetadata(`<div>{{ literal }}</div>`, {
|
||||||
inline: true
|
inline: true,
|
||||||
})
|
})
|
||||||
expect(code).toMatch(`toDisplayString(literal)`)
|
expect(code).toMatch(`toDisplayString(literal)`)
|
||||||
// #7973 should skip patch for literal const
|
// #7973 should skip patch for literal const
|
||||||
expect(code).not.toMatch(
|
expect(code).not.toMatch(
|
||||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
|
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -581,17 +585,17 @@ describe('compiler: expression transform', () => {
|
||||||
expect(code).toMatch(`toDisplayString($setup.literal)`)
|
expect(code).toMatch(`toDisplayString($setup.literal)`)
|
||||||
// #7973 should skip patch for literal const
|
// #7973 should skip patch for literal const
|
||||||
expect(code).not.toMatch(
|
expect(code).not.toMatch(
|
||||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
|
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('reactive const handling', () => {
|
test('reactive const handling', () => {
|
||||||
const { code } = compileWithBindingMetadata(`<div>{{ reactive }}</div>`, {
|
const { code } = compileWithBindingMetadata(`<div>{{ reactive }}</div>`, {
|
||||||
inline: true
|
inline: true,
|
||||||
})
|
})
|
||||||
// #7973 should not skip patch for reactive const
|
// #7973 should not skip patch for reactive const
|
||||||
expect(code).toMatch(
|
expect(code).toMatch(
|
||||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
|
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import {
|
import {
|
||||||
CompilerOptions,
|
type CompilerOptions,
|
||||||
|
type ElementNode,
|
||||||
|
ErrorCodes,
|
||||||
|
NodeTypes,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
ElementNode,
|
|
||||||
NodeTypes,
|
|
||||||
ErrorCodes
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import { transformOn } from '../../src/transforms/vOn'
|
import { transformOn } from '../../src/transforms/vOn'
|
||||||
|
@ -19,13 +19,13 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
||||||
nodeTransforms: [
|
nodeTransforms: [
|
||||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||||
transformSlotOutlet,
|
transformSlotOutlet,
|
||||||
transformElement
|
transformElement,
|
||||||
],
|
],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
on: transformOn,
|
on: transformOn,
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT,
|
callee: RENDER_SLOT,
|
||||||
arguments: [`$slots`, `"default"`]
|
arguments: [`$slots`, `"default"`],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT,
|
callee: RENDER_SLOT,
|
||||||
arguments: [`$slots`, `"foo"`]
|
arguments: [`$slots`, `"foo"`],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -59,15 +59,15 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
{
|
{
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('dynamically named slot outlet w/ prefixIdentifiers: true', () => {
|
test('dynamically named slot outlet w/ prefixIdentifiers: true', () => {
|
||||||
const ast = parseWithSlots(`<slot :name="foo + bar" />`, {
|
const ast = parseWithSlots(`<slot :name="foo + bar" />`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
@ -80,23 +80,23 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
{
|
{
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.foo`,
|
content: `_ctx.foo`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
` + `,
|
` + `,
|
||||||
{
|
{
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.bar`,
|
content: `_ctx.bar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('default slot outlet with props', () => {
|
test('default slot outlet with props', () => {
|
||||||
const ast = parseWithSlots(
|
const ast = parseWithSlots(
|
||||||
`<slot foo="bar" :baz="qux" :foo-bar="foo-bar" />`
|
`<slot foo="bar" :baz="qux" :foo-bar="foo-bar" />`,
|
||||||
)
|
)
|
||||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
@ -110,36 +110,36 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `bar`,
|
content: `bar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `baz`,
|
content: `baz`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `qux`,
|
content: `qux`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `foo-bar`,
|
content: `foo-bar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -158,26 +158,26 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `bar`,
|
content: `bar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `baz`,
|
content: `baz`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `qux`,
|
content: `qux`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -196,26 +196,26 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `bar`,
|
content: `bar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `baz`,
|
content: `baz`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `qux`,
|
content: `qux`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -234,11 +234,11 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: `div`
|
tag: `div`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -257,11 +257,11 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: `div`
|
tag: `div`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -279,14 +279,14 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `bar`,
|
content: `bar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
@ -294,11 +294,11 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: `div`
|
tag: `div`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -316,14 +316,14 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `bar`,
|
content: `bar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
@ -331,11 +331,11 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: `div`
|
tag: `div`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -344,11 +344,11 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT,
|
callee: RENDER_SLOT,
|
||||||
arguments: [`$slots`, `"default"`, `{}`, `undefined`, `true`]
|
arguments: [`$slots`, `"default"`, `{}`, `undefined`, `true`],
|
||||||
})
|
})
|
||||||
const fallback = parseWithSlots(`<slot>fallback</slot>`, {
|
const fallback = parseWithSlots(`<slot>fallback</slot>`, {
|
||||||
slotted: false,
|
slotted: false,
|
||||||
scopeId: 'foo'
|
scopeId: 'foo',
|
||||||
})
|
})
|
||||||
|
|
||||||
const child = {
|
const child = {
|
||||||
|
@ -357,14 +357,14 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `fallback`
|
content: `fallback`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
expect((fallback.children[0] as ElementNode).codegenNode).toMatchObject({
|
expect((fallback.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT,
|
callee: RENDER_SLOT,
|
||||||
arguments: [`$slots`, `"default"`, `{}`, child, `true`]
|
arguments: [`$slots`, `"default"`, `{}`, child, `true`],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -379,14 +379,14 @@ describe('compiler: transform <slot> outlets', () => {
|
||||||
start: {
|
start: {
|
||||||
offset: index,
|
offset: index,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 1
|
column: index + 1,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
offset: index + 5,
|
offset: index + 5,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 6
|
column: index + 6,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import {
|
import {
|
||||||
CompilerOptions,
|
type CompilerOptions,
|
||||||
baseParse as parse,
|
type ElementNode,
|
||||||
transform,
|
type ForNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
generate,
|
generate,
|
||||||
ForNode,
|
baseParse as parse,
|
||||||
ElementNode
|
transform,
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformFor } from '../../src/transforms/vFor'
|
import { transformFor } from '../../src/transforms/vFor'
|
||||||
import { transformText } from '../../src/transforms/transformText'
|
import { transformText } from '../../src/transforms/transformText'
|
||||||
|
@ -22,9 +22,9 @@ function transformWithTextOpt(template: string, options: CompilerOptions = {}) {
|
||||||
transformFor,
|
transformFor,
|
||||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||||
transformElement,
|
transformElement,
|
||||||
transformText
|
transformText,
|
||||||
],
|
],
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -35,8 +35,8 @@ describe('compiler: transform text', () => {
|
||||||
expect(root.children[0]).toMatchObject({
|
expect(root.children[0]).toMatchObject({
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -51,8 +51,8 @@ describe('compiler: transform text', () => {
|
||||||
` + `,
|
` + `,
|
||||||
{ type: NodeTypes.TEXT, content: ` bar ` },
|
{ type: NodeTypes.TEXT, content: ` bar ` },
|
||||||
` + `,
|
` + `,
|
||||||
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } }
|
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -75,12 +75,12 @@ describe('compiler: transform text', () => {
|
||||||
` + `,
|
` + `,
|
||||||
{ type: NodeTypes.TEXT, content: ` bar ` },
|
{ type: NodeTypes.TEXT, content: ` bar ` },
|
||||||
` + `,
|
` + `,
|
||||||
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } }
|
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } },
|
||||||
]
|
],
|
||||||
|
},
|
||||||
|
genFlagText(PatchFlags.TEXT),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
genFlagText(PatchFlags.TEXT)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
|
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -99,11 +99,11 @@ describe('compiler: transform text', () => {
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `hello`
|
content: `hello`,
|
||||||
}
|
},
|
||||||
// should have no flag
|
// should have no flag
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
|
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -111,7 +111,7 @@ describe('compiler: transform text', () => {
|
||||||
|
|
||||||
test('consecutive text mixed with elements', () => {
|
test('consecutive text mixed with elements', () => {
|
||||||
const root = transformWithTextOpt(
|
const root = transformWithTextOpt(
|
||||||
`<div/>{{ foo }} bar {{ baz }}<div/>hello<div/>`
|
`<div/>{{ foo }} bar {{ baz }}<div/>hello<div/>`,
|
||||||
)
|
)
|
||||||
expect(root.children.length).toBe(5)
|
expect(root.children.length).toBe(5)
|
||||||
expect(root.children[0].type).toBe(NodeTypes.ELEMENT)
|
expect(root.children[0].type).toBe(NodeTypes.ELEMENT)
|
||||||
|
@ -128,12 +128,12 @@ describe('compiler: transform text', () => {
|
||||||
` + `,
|
` + `,
|
||||||
{ type: NodeTypes.TEXT, content: ` bar ` },
|
{ type: NodeTypes.TEXT, content: ` bar ` },
|
||||||
` + `,
|
` + `,
|
||||||
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } }
|
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } },
|
||||||
]
|
],
|
||||||
|
},
|
||||||
|
genFlagText(PatchFlags.TEXT),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
genFlagText(PatchFlags.TEXT)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
|
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
|
||||||
expect(root.children[3]).toMatchObject({
|
expect(root.children[3]).toMatchObject({
|
||||||
|
@ -144,10 +144,10 @@ describe('compiler: transform text', () => {
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `hello`
|
content: `hello`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(root.children[4].type).toBe(NodeTypes.ELEMENT)
|
expect(root.children[4].type).toBe(NodeTypes.ELEMENT)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -155,21 +155,21 @@ describe('compiler: transform text', () => {
|
||||||
|
|
||||||
test('<template v-for>', () => {
|
test('<template v-for>', () => {
|
||||||
const root = transformWithTextOpt(
|
const root = transformWithTextOpt(
|
||||||
`<template v-for="i in list">foo</template>`
|
`<template v-for="i in list">foo</template>`,
|
||||||
)
|
)
|
||||||
expect(root.children[0].type).toBe(NodeTypes.FOR)
|
expect(root.children[0].type).toBe(NodeTypes.FOR)
|
||||||
const forNode = root.children[0] as ForNode
|
const forNode = root.children[0] as ForNode
|
||||||
// should convert template v-for text children because they are inside
|
// should convert template v-for text children because they are inside
|
||||||
// fragments
|
// fragments
|
||||||
expect(forNode.children[0]).toMatchObject({
|
expect(forNode.children[0]).toMatchObject({
|
||||||
type: NodeTypes.TEXT_CALL
|
type: NodeTypes.TEXT_CALL,
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('with prefixIdentifiers: true', () => {
|
test('with prefixIdentifiers: true', () => {
|
||||||
const root = transformWithTextOpt(`{{ foo }} bar {{ baz + qux }}`, {
|
const root = transformWithTextOpt(`{{ foo }} bar {{ baz + qux }}`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(root.children.length).toBe(1)
|
expect(root.children.length).toBe(1)
|
||||||
expect(root.children[0]).toMatchObject({
|
expect(root.children[0]).toMatchObject({
|
||||||
|
@ -183,15 +183,15 @@ describe('compiler: transform text', () => {
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [{ content: `_ctx.baz` }, ` + `, { content: `_ctx.qux` }]
|
children: [{ content: `_ctx.baz` }, ` + `, { content: `_ctx.qux` }],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect(
|
expect(
|
||||||
generate(root, {
|
generate(root, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}).code
|
}).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -210,12 +210,12 @@ describe('compiler: transform text', () => {
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'foo'
|
content: 'foo',
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
genFlagText(PatchFlags.TEXT),
|
||||||
|
],
|
||||||
},
|
},
|
||||||
genFlagText(PatchFlags.TEXT)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,37 +1,37 @@
|
||||||
import {
|
import {
|
||||||
|
type CallExpression,
|
||||||
|
type CompilerOptions,
|
||||||
|
type ElementNode,
|
||||||
|
ErrorCodes,
|
||||||
|
NodeTypes,
|
||||||
|
type ObjectExpression,
|
||||||
|
type VNodeCall,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
ElementNode,
|
|
||||||
ObjectExpression,
|
|
||||||
CompilerOptions,
|
|
||||||
ErrorCodes,
|
|
||||||
VNodeCall,
|
|
||||||
NodeTypes,
|
|
||||||
CallExpression
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformBind } from '../../src/transforms/vBind'
|
import { transformBind } from '../../src/transforms/vBind'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import {
|
import {
|
||||||
CAMELIZE,
|
CAMELIZE,
|
||||||
|
NORMALIZE_PROPS,
|
||||||
helperNameMap,
|
helperNameMap,
|
||||||
NORMALIZE_PROPS
|
|
||||||
} from '../../src/runtimeHelpers'
|
} from '../../src/runtimeHelpers'
|
||||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
|
|
||||||
function parseWithVBind(
|
function parseWithVBind(
|
||||||
template: string,
|
template: string,
|
||||||
options: CompilerOptions = {}
|
options: CompilerOptions = {},
|
||||||
): ElementNode {
|
): ElementNode {
|
||||||
const ast = parse(template)
|
const ast = parse(template)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [
|
nodeTransforms: [
|
||||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||||
transformElement
|
transformElement,
|
||||||
],
|
],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast.children[0] as ElementNode
|
return ast.children[0] as ElementNode
|
||||||
}
|
}
|
||||||
|
@ -47,13 +47,13 @@ describe('compiler: transform v-bind', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 13
|
column: 13,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 15
|
column: 15,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
|
@ -61,14 +61,14 @@ describe('compiler: transform v-bind', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 17
|
column: 17,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 19
|
column: 19,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -81,17 +81,17 @@ describe('compiler: transform v-bind', () => {
|
||||||
isStatic: true,
|
isStatic: true,
|
||||||
loc: {
|
loc: {
|
||||||
start: { line: 1, column: 13, offset: 12 },
|
start: { line: 1, column: 13, offset: 12 },
|
||||||
end: { line: 1, column: 15, offset: 14 }
|
end: { line: 1, column: 15, offset: 14 },
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
loc: {
|
loc: {
|
||||||
start: { line: 1, column: 13, offset: 12 },
|
start: { line: 1, column: 13, offset: 12 },
|
||||||
end: { line: 1, column: 15, offset: 14 }
|
end: { line: 1, column: 15, offset: 14 },
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -101,12 +101,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -123,16 +123,16 @@ describe('compiler: transform v-bind', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `id || ""`,
|
content: `id || ""`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -145,23 +145,23 @@ describe('compiler: transform v-bind', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 6
|
column: 6,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 19
|
column: 19,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `arg`,
|
content: `arg`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: ``,
|
content: ``,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -171,12 +171,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -186,12 +186,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -208,22 +208,22 @@ describe('compiler: transform v-bind', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `_${helperNameMap[CAMELIZE]}(foo || "")`,
|
content: `_${helperNameMap[CAMELIZE]}(foo || "")`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.camel modifier w/ dynamic arg + prefixIdentifiers', () => {
|
test('.camel modifier w/ dynamic arg + prefixIdentifiers', () => {
|
||||||
const node = parseWithVBind(`<div v-bind:[foo(bar)].camel="id"/>`, {
|
const node = parseWithVBind(`<div v-bind:[foo(bar)].camel="id"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
||||||
expect(props).toMatchObject({
|
expect(props).toMatchObject({
|
||||||
|
@ -243,17 +243,17 @@ describe('compiler: transform v-bind', () => {
|
||||||
{ content: `_ctx.bar` },
|
{ content: `_ctx.bar` },
|
||||||
`)`,
|
`)`,
|
||||||
`) || ""`,
|
`) || ""`,
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `_ctx.id`,
|
content: `_ctx.id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -263,12 +263,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `.fooBar`,
|
content: `.fooBar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -278,12 +278,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `.fooBar`,
|
content: `.fooBar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -300,22 +300,22 @@ describe('compiler: transform v-bind', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: '`.${fooBar || ""}`',
|
content: '`.${fooBar || ""}`',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('.prop modifier w/ dynamic arg + prefixIdentifiers', () => {
|
test('.prop modifier w/ dynamic arg + prefixIdentifiers', () => {
|
||||||
const node = parseWithVBind(`<div v-bind:[foo(bar)].prop="id"/>`, {
|
const node = parseWithVBind(`<div v-bind:[foo(bar)].prop="id"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
||||||
expect(props).toMatchObject({
|
expect(props).toMatchObject({
|
||||||
|
@ -335,17 +335,17 @@ describe('compiler: transform v-bind', () => {
|
||||||
{ content: `_ctx.bar` },
|
{ content: `_ctx.bar` },
|
||||||
`)`,
|
`)`,
|
||||||
`) || ""`,
|
`) || ""`,
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `_ctx.id`,
|
content: `_ctx.id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -355,12 +355,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `.fooBar`,
|
content: `.fooBar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -370,12 +370,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `.fooBar`,
|
content: `.fooBar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -385,12 +385,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `^foo-bar`,
|
content: `^foo-bar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `id`,
|
content: `id`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -400,12 +400,12 @@ describe('compiler: transform v-bind', () => {
|
||||||
expect(props.properties[0]).toMatchObject({
|
expect(props.properties[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `^foo-bar`,
|
content: `^foo-bar`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `fooBar`,
|
content: `fooBar`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,23 +7,23 @@ import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
import {
|
import {
|
||||||
ForNode,
|
ConstantTypes,
|
||||||
|
type ElementNode,
|
||||||
|
type ForCodegenNode,
|
||||||
|
type ForNode,
|
||||||
|
type InterpolationNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
SimpleExpressionNode,
|
type SimpleExpressionNode,
|
||||||
ElementNode,
|
|
||||||
InterpolationNode,
|
|
||||||
ForCodegenNode,
|
|
||||||
ConstantTypes
|
|
||||||
} from '../../src/ast'
|
} from '../../src/ast'
|
||||||
import { ErrorCodes } from '../../src/errors'
|
import { ErrorCodes } from '../../src/errors'
|
||||||
import { CompilerOptions, generate } from '../../src'
|
import { type CompilerOptions, generate } from '../../src'
|
||||||
import { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers'
|
import { FRAGMENT, RENDER_LIST, RENDER_SLOT } from '../../src/runtimeHelpers'
|
||||||
import { PatchFlags } from '@vue/shared'
|
import { PatchFlags } from '@vue/shared'
|
||||||
import { createObjectMatcher, genFlagText } from '../testUtils'
|
import { createObjectMatcher, genFlagText } from '../testUtils'
|
||||||
|
|
||||||
function parseWithForTransform(
|
function parseWithForTransform(
|
||||||
template: string,
|
template: string,
|
||||||
options: CompilerOptions = {}
|
options: CompilerOptions = {},
|
||||||
) {
|
) {
|
||||||
const ast = parse(template, options)
|
const ast = parse(template, options)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
|
@ -32,16 +32,16 @@ function parseWithForTransform(
|
||||||
transformFor,
|
transformFor,
|
||||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||||
transformSlotOutlet,
|
transformSlotOutlet,
|
||||||
transformElement
|
transformElement,
|
||||||
],
|
],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
root: ast,
|
root: ast,
|
||||||
node: ast.children[0] as ForNode & { codegenNode: ForCodegenNode }
|
node: ast.children[0] as ForNode & { codegenNode: ForCodegenNode },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ describe('compiler: v-for', () => {
|
||||||
describe('transform', () => {
|
describe('transform', () => {
|
||||||
test('number expression', () => {
|
test('number expression', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="index in 5" />'
|
'<span v-for="index in 5" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
|
@ -59,7 +59,7 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('value', () => {
|
test('value', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(item) in items" />'
|
'<span v-for="(item) in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
|
@ -69,31 +69,31 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('object de-structured value', () => {
|
test('object de-structured value', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="({ id, value }) in items" />'
|
'<span v-for="({ id, value }) in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
||||||
'{ id, value }'
|
'{ id, value }',
|
||||||
)
|
)
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('array de-structured value', () => {
|
test('array de-structured value', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="([ id, value ]) in items" />'
|
'<span v-for="([ id, value ]) in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
||||||
'[ id, value ]'
|
'[ id, value ]',
|
||||||
)
|
)
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('value and key', () => {
|
test('value and key', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(item, key) in items" />'
|
'<span v-for="(item, key) in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
|
@ -104,13 +104,13 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('value, key and index', () => {
|
test('value, key and index', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(value, key, index) in items" />'
|
'<span v-for="(value, key, index) in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
'index'
|
'index',
|
||||||
)
|
)
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
|
@ -118,12 +118,12 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('skipped key', () => {
|
test('skipped key', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(value,,index) in items" />'
|
'<span v-for="(value,,index) in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
'index'
|
'index',
|
||||||
)
|
)
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
|
@ -131,12 +131,12 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('skipped value and key', () => {
|
test('skipped value and key', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="(,,index) in items" />'
|
'<span v-for="(,,index) in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
'index'
|
'index',
|
||||||
)
|
)
|
||||||
expect(forNode.valueAlias).toBeUndefined()
|
expect(forNode.valueAlias).toBeUndefined()
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
|
@ -144,7 +144,7 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('unbracketed value', () => {
|
test('unbracketed value', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="item in items" />'
|
'<span v-for="item in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||||
|
@ -154,7 +154,7 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('unbracketed value and key', () => {
|
test('unbracketed value and key', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="item, key in items" />'
|
'<span v-for="item, key in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
|
@ -165,13 +165,13 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('unbracketed value, key and index', () => {
|
test('unbracketed value, key and index', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="value, key, index in items" />'
|
'<span v-for="value, key, index in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).not.toBeUndefined()
|
expect(forNode.keyAlias).not.toBeUndefined()
|
||||||
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
expect((forNode.keyAlias as SimpleExpressionNode).content).toBe('key')
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
'index'
|
'index',
|
||||||
)
|
)
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
|
@ -179,12 +179,12 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('unbracketed skipped key', () => {
|
test('unbracketed skipped key', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for="value, , index in items" />'
|
'<span v-for="value, , index in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
'index'
|
'index',
|
||||||
)
|
)
|
||||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
|
@ -192,12 +192,12 @@ describe('compiler: v-for', () => {
|
||||||
|
|
||||||
test('unbracketed skipped value and key', () => {
|
test('unbracketed skipped value and key', () => {
|
||||||
const { node: forNode } = parseWithForTransform(
|
const { node: forNode } = parseWithForTransform(
|
||||||
'<span v-for=", , index in items" />'
|
'<span v-for=", , index in items" />',
|
||||||
)
|
)
|
||||||
expect(forNode.keyAlias).toBeUndefined()
|
expect(forNode.keyAlias).toBeUndefined()
|
||||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||||
'index'
|
'index',
|
||||||
)
|
)
|
||||||
expect(forNode.valueAlias).toBeUndefined()
|
expect(forNode.valueAlias).toBeUndefined()
|
||||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||||
|
@ -212,8 +212,8 @@ describe('compiler: v-for', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_FOR_NO_EXPRESSION
|
code: ErrorCodes.X_V_FOR_NO_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -224,8 +224,8 @@ describe('compiler: v-for', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION
|
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -236,8 +236,8 @@ describe('compiler: v-for', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION
|
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -248,8 +248,8 @@ describe('compiler: v-for', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION
|
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -260,8 +260,8 @@ describe('compiler: v-for', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION
|
code: ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -272,14 +272,14 @@ describe('compiler: v-for', () => {
|
||||||
<template v-for="item in items">
|
<template v-for="item in items">
|
||||||
<div :key="item.id"/>
|
<div :key="item.id"/>
|
||||||
</template>`,
|
</template>`,
|
||||||
{ onError }
|
{ onError },
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT
|
code: ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
// should not warn on nested v-for keys
|
// should not warn on nested v-for keys
|
||||||
|
@ -288,7 +288,7 @@ describe('compiler: v-for', () => {
|
||||||
<template v-for="item in items">
|
<template v-for="item in items">
|
||||||
<div v-for="c in item.children" :key="c.id"/>
|
<div v-for="c in item.children" :key="c.id"/>
|
||||||
</template>`,
|
</template>`,
|
||||||
{ onError }
|
{ onError },
|
||||||
)
|
)
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
})
|
})
|
||||||
|
@ -315,7 +315,7 @@ describe('compiler: v-for', () => {
|
||||||
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
||||||
expect(forNode.source.loc.end.line).toBe(1)
|
expect(forNode.source.loc.end.line).toBe(1)
|
||||||
expect(forNode.source.loc.end.column).toBe(
|
expect(forNode.source.loc.end.column).toBe(
|
||||||
itemsOffset + 1 + `items`.length
|
itemsOffset + 1 + `items`.length,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ describe('compiler: v-for', () => {
|
||||||
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
||||||
expect(forNode.source.loc.end.line).toBe(1)
|
expect(forNode.source.loc.end.line).toBe(1)
|
||||||
expect(forNode.source.loc.end.column).toBe(
|
expect(forNode.source.loc.end.column).toBe(
|
||||||
itemsOffset + 1 + `items`.length
|
itemsOffset + 1 + `items`.length,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -363,7 +363,7 @@ describe('compiler: v-for', () => {
|
||||||
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
||||||
expect(forNode.source.loc.end.line).toBe(1)
|
expect(forNode.source.loc.end.line).toBe(1)
|
||||||
expect(forNode.source.loc.end.column).toBe(
|
expect(forNode.source.loc.end.column).toBe(
|
||||||
itemsOffset + 1 + `items`.length
|
itemsOffset + 1 + `items`.length,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -405,7 +405,7 @@ describe('compiler: v-for', () => {
|
||||||
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
||||||
expect(forNode.source.loc.end.line).toBe(1)
|
expect(forNode.source.loc.end.line).toBe(1)
|
||||||
expect(forNode.source.loc.end.column).toBe(
|
expect(forNode.source.loc.end.column).toBe(
|
||||||
itemsOffset + 1 + `items`.length
|
itemsOffset + 1 + `items`.length,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -438,7 +438,7 @@ describe('compiler: v-for', () => {
|
||||||
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
expect(forNode.source.loc.start.column).toBe(itemsOffset + 1)
|
||||||
expect(forNode.source.loc.end.line).toBe(1)
|
expect(forNode.source.loc.end.line).toBe(1)
|
||||||
expect(forNode.source.loc.end.column).toBe(
|
expect(forNode.source.loc.end.column).toBe(
|
||||||
itemsOffset + 1 + `items`.length
|
itemsOffset + 1 + `items`.length,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -446,18 +446,18 @@ describe('compiler: v-for', () => {
|
||||||
describe('prefixIdentifiers: true', () => {
|
describe('prefixIdentifiers: true', () => {
|
||||||
test('should prefix v-for source', () => {
|
test('should prefix v-for source', () => {
|
||||||
const { node } = parseWithForTransform(`<div v-for="i in list"/>`, {
|
const { node } = parseWithForTransform(`<div v-for="i in list"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(node.source).toMatchObject({
|
expect(node.source).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.list`
|
content: `_ctx.list`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix v-for source w/ complex expression', () => {
|
test('should prefix v-for source w/ complex expression', () => {
|
||||||
const { node } = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="i in list.concat([foo])"/>`,
|
`<div v-for="i in list.concat([foo])"/>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(node.source).toMatchObject({
|
expect(node.source).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -467,31 +467,31 @@ describe('compiler: v-for', () => {
|
||||||
{ content: `concat` },
|
{ content: `concat` },
|
||||||
`([`,
|
`([`,
|
||||||
{ content: `_ctx.foo` },
|
{ content: `_ctx.foo` },
|
||||||
`])`
|
`])`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix v-for alias', () => {
|
test('should not prefix v-for alias', () => {
|
||||||
const { node } = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="i in list">{{ i }}{{ j }}</div>`,
|
`<div v-for="i in list">{{ i }}{{ j }}</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
const div = node.children[0] as ElementNode
|
const div = node.children[0] as ElementNode
|
||||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `i`
|
content: `i`,
|
||||||
})
|
})
|
||||||
expect((div.children[1] as InterpolationNode).content).toMatchObject({
|
expect((div.children[1] as InterpolationNode).content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.j`
|
content: `_ctx.j`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not prefix v-for aliases (multiple)', () => {
|
test('should not prefix v-for aliases (multiple)', () => {
|
||||||
const { node } = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div v-for="(i, j, k) in list">{{ i + j + k }}{{ l }}</div>`,
|
`<div v-for="(i, j, k) in list">{{ i + j + k }}{{ l }}</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
const div = node.children[0] as ElementNode
|
const div = node.children[0] as ElementNode
|
||||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||||
|
@ -501,23 +501,23 @@ describe('compiler: v-for', () => {
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `j` },
|
{ content: `j` },
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `k` }
|
{ content: `k` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect((div.children[1] as InterpolationNode).content).toMatchObject({
|
expect((div.children[1] as InterpolationNode).content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.l`
|
content: `_ctx.l`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should prefix id outside of v-for', () => {
|
test('should prefix id outside of v-for', () => {
|
||||||
const { node } = parseWithForTransform(
|
const { node } = parseWithForTransform(
|
||||||
`<div><div v-for="i in list" />{{ i }}</div>`,
|
`<div><div v-for="i in list" />{{ i }}</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect((node.children[1] as InterpolationNode).content).toMatchObject({
|
expect((node.children[1] as InterpolationNode).content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.i`
|
content: `_ctx.i`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -526,7 +526,7 @@ describe('compiler: v-for', () => {
|
||||||
`<div v-for="i in list">
|
`<div v-for="i in list">
|
||||||
<div v-for="i in list">{{ i + j }}</div>{{ i }}
|
<div v-for="i in list">{{ i + j }}</div>{{ i }}
|
||||||
</div>`,
|
</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
const outerDiv = node.children[0] as ElementNode
|
const outerDiv = node.children[0] as ElementNode
|
||||||
const innerFor = outerDiv.children[0] as ForNode
|
const innerFor = outerDiv.children[0] as ForNode
|
||||||
|
@ -534,7 +534,7 @@ describe('compiler: v-for', () => {
|
||||||
.children[0] as InterpolationNode
|
.children[0] as InterpolationNode
|
||||||
expect(innerExp.content).toMatchObject({
|
expect(innerExp.content).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [{ content: 'i' }, ` + `, { content: `_ctx.j` }]
|
children: [{ content: 'i' }, ` + `, { content: `_ctx.j` }],
|
||||||
})
|
})
|
||||||
|
|
||||||
// when an inner v-for shadows a variable of an outer v-for and exit,
|
// when an inner v-for shadows a variable of an outer v-for and exit,
|
||||||
|
@ -542,7 +542,7 @@ describe('compiler: v-for', () => {
|
||||||
const outerExp = outerDiv.children[1] as InterpolationNode
|
const outerExp = outerDiv.children[1] as InterpolationNode
|
||||||
expect(outerExp.content).toMatchObject({
|
expect(outerExp.content).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `i`
|
content: `i`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -551,7 +551,7 @@ describe('compiler: v-for', () => {
|
||||||
`<div v-for="({ foo = bar, baz: [qux = quux] }) in list">
|
`<div v-for="({ foo = bar, baz: [qux = quux] }) in list">
|
||||||
{{ foo + bar + baz + qux + quux }}
|
{{ foo + bar + baz + qux + quux }}
|
||||||
</div>`,
|
</div>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(node.valueAlias!).toMatchObject({
|
expect(node.valueAlias!).toMatchObject({
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
|
@ -564,8 +564,8 @@ describe('compiler: v-for', () => {
|
||||||
{ content: `qux` },
|
{ content: `qux` },
|
||||||
` = `,
|
` = `,
|
||||||
{ content: `_ctx.quux` },
|
{ content: `_ctx.quux` },
|
||||||
`] }`
|
`] }`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
const div = node.children[0] as ElementNode
|
const div = node.children[0] as ElementNode
|
||||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||||
|
@ -579,17 +579,17 @@ describe('compiler: v-for', () => {
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `qux` },
|
{ content: `qux` },
|
||||||
` + `,
|
` + `,
|
||||||
{ content: `_ctx.quux` }
|
{ content: `_ctx.quux` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('element v-for key expression prefixing', () => {
|
test('element v-for key expression prefixing', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(
|
} = parseWithForTransform(
|
||||||
'<div v-for="item in items" :key="itemKey(item)">test</div>',
|
'<div v-for="item in items" :key="itemKey(item)">test</div>',
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
const innerBlock = codegenNode.children.arguments[1].returns
|
const innerBlock = codegenNode.children.arguments[1].returns
|
||||||
expect(innerBlock).toMatchObject({
|
expect(innerBlock).toMatchObject({
|
||||||
|
@ -604,20 +604,20 @@ describe('compiler: v-for', () => {
|
||||||
`(`,
|
`(`,
|
||||||
// should NOT prefix in scope variables
|
// should NOT prefix in scope variables
|
||||||
{ content: `item` },
|
{ content: `item` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// #2085
|
// #2085
|
||||||
test('template v-for key expression prefixing', () => {
|
test('template v-for key expression prefixing', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(
|
} = parseWithForTransform(
|
||||||
'<template v-for="item in items" :key="itemKey(item)">test</template>',
|
'<template v-for="item in items" :key="itemKey(item)">test</template>',
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
const innerBlock = codegenNode.children.arguments[1].returns
|
const innerBlock = codegenNode.children.arguments[1].returns
|
||||||
expect(innerBlock).toMatchObject({
|
expect(innerBlock).toMatchObject({
|
||||||
|
@ -632,19 +632,19 @@ describe('compiler: v-for', () => {
|
||||||
`(`,
|
`(`,
|
||||||
// should NOT prefix in scope variables
|
// should NOT prefix in scope variables
|
||||||
{ content: `item` },
|
{ content: `item` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('template v-for key no prefixing on attribute key', () => {
|
test('template v-for key no prefixing on attribute key', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(
|
} = parseWithForTransform(
|
||||||
'<template v-for="item in items" key="key">test</template>',
|
'<template v-for="item in items" key="key">test</template>',
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
const innerBlock = codegenNode.children.arguments[1].returns
|
const innerBlock = codegenNode.children.arguments[1].returns
|
||||||
expect(innerBlock).toMatchObject({
|
expect(innerBlock).toMatchObject({
|
||||||
|
@ -653,9 +653,9 @@ describe('compiler: v-for', () => {
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
key: {
|
key: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'key'
|
content: 'key',
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -665,7 +665,7 @@ describe('compiler: v-for', () => {
|
||||||
node: ForCodegenNode,
|
node: ForCodegenNode,
|
||||||
keyed: boolean = false,
|
keyed: boolean = false,
|
||||||
customReturn: boolean = false,
|
customReturn: boolean = false,
|
||||||
disableTracking: boolean = true
|
disableTracking: boolean = true,
|
||||||
) {
|
) {
|
||||||
expect(node).toMatchObject({
|
expect(node).toMatchObject({
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
|
@ -687,32 +687,34 @@ describe('compiler: v-for', () => {
|
||||||
? {}
|
? {}
|
||||||
: {
|
: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
isBlock: disableTracking
|
isBlock: disableTracking,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
const renderListArgs = node.children.arguments
|
const renderListArgs = node.children.arguments
|
||||||
return {
|
return {
|
||||||
source: renderListArgs[0] as SimpleExpressionNode,
|
source: renderListArgs[0] as SimpleExpressionNode,
|
||||||
params: (renderListArgs[1] as any).params,
|
params: (renderListArgs[1] as any).params,
|
||||||
returns: (renderListArgs[1] as any).returns,
|
returns: (renderListArgs[1] as any).returns,
|
||||||
innerVNodeCall: customReturn ? null : (renderListArgs[1] as any).returns
|
innerVNodeCall: customReturn
|
||||||
|
? null
|
||||||
|
: (renderListArgs[1] as any).returns,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
test('basic v-for', () => {
|
test('basic v-for', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<span v-for="(item) in items" />')
|
} = parseWithForTransform('<span v-for="(item) in items" />')
|
||||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
params: [{ content: `item` }],
|
params: [{ content: `item` }],
|
||||||
innerVNodeCall: {
|
innerVNodeCall: {
|
||||||
tag: `"span"`
|
tag: `"span"`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -720,11 +722,11 @@ describe('compiler: v-for', () => {
|
||||||
test('value + key + index', () => {
|
test('value + key + index', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<span v-for="(item, key, index) in items" />')
|
} = parseWithForTransform('<span v-for="(item, key, index) in items" />')
|
||||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
params: [{ content: `item` }, { content: `key` }, { content: `index` }]
|
params: [{ content: `item` }, { content: `key` }, { content: `index` }],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -732,11 +734,11 @@ describe('compiler: v-for', () => {
|
||||||
test('skipped value', () => {
|
test('skipped value', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<span v-for="(, key, index) in items" />')
|
} = parseWithForTransform('<span v-for="(, key, index) in items" />')
|
||||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
params: [{ content: `_` }, { content: `key` }, { content: `index` }]
|
params: [{ content: `_` }, { content: `key` }, { content: `index` }],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -744,11 +746,11 @@ describe('compiler: v-for', () => {
|
||||||
test('skipped key', () => {
|
test('skipped key', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<span v-for="(item,,index) in items" />')
|
} = parseWithForTransform('<span v-for="(item,,index) in items" />')
|
||||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
params: [{ content: `item` }, { content: `__` }, { content: `index` }]
|
params: [{ content: `item` }, { content: `__` }, { content: `index` }],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -756,11 +758,11 @@ describe('compiler: v-for', () => {
|
||||||
test('skipped value & key', () => {
|
test('skipped value & key', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<span v-for="(,,index) in items" />')
|
} = parseWithForTransform('<span v-for="(,,index) in items" />')
|
||||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
params: [{ content: `_` }, { content: `__` }, { content: `index` }]
|
params: [{ content: `_` }, { content: `__` }, { content: `index` }],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -768,9 +770,9 @@ describe('compiler: v-for', () => {
|
||||||
test('v-for with constant expression', () => {
|
test('v-for with constant expression', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<p v-for="item in 10">{{item}}</p>', {
|
} = parseWithForTransform('<p v-for="item in 10">{{item}}</p>', {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -778,8 +780,8 @@ describe('compiler: v-for', () => {
|
||||||
codegenNode,
|
codegenNode,
|
||||||
false /* keyed */,
|
false /* keyed */,
|
||||||
false /* customReturn */,
|
false /* customReturn */,
|
||||||
false /* disableTracking */
|
false /* disableTracking */,
|
||||||
)
|
),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
source: { content: `10`, constType: ConstantTypes.CAN_STRINGIFY },
|
source: { content: `10`, constType: ConstantTypes.CAN_STRINGIFY },
|
||||||
params: [{ content: `item` }],
|
params: [{ content: `item` }],
|
||||||
|
@ -793,11 +795,11 @@ describe('compiler: v-for', () => {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'item',
|
content: 'item',
|
||||||
isStatic: false,
|
isStatic: false,
|
||||||
constType: ConstantTypes.NOT_CONSTANT
|
constType: ConstantTypes.NOT_CONSTANT,
|
||||||
}
|
},
|
||||||
|
},
|
||||||
|
patchFlag: genFlagText(PatchFlags.TEXT),
|
||||||
},
|
},
|
||||||
patchFlag: genFlagText(PatchFlags.TEXT)
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -805,9 +807,9 @@ describe('compiler: v-for', () => {
|
||||||
test('template v-for', () => {
|
test('template v-for', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(
|
} = parseWithForTransform(
|
||||||
'<template v-for="item in items">hello<span/></template>'
|
'<template v-for="item in items">hello<span/></template>',
|
||||||
)
|
)
|
||||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
|
@ -818,10 +820,10 @@ describe('compiler: v-for', () => {
|
||||||
isBlock: true,
|
isBlock: true,
|
||||||
children: [
|
children: [
|
||||||
{ type: NodeTypes.TEXT, content: `hello` },
|
{ type: NodeTypes.TEXT, content: `hello` },
|
||||||
{ type: NodeTypes.ELEMENT, tag: `span` }
|
{ type: NodeTypes.ELEMENT, tag: `span` },
|
||||||
],
|
],
|
||||||
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT)
|
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -829,19 +831,19 @@ describe('compiler: v-for', () => {
|
||||||
test('template v-for w/ <slot/>', () => {
|
test('template v-for w/ <slot/>', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(
|
} = parseWithForTransform(
|
||||||
'<template v-for="item in items"><slot/></template>'
|
'<template v-for="item in items"><slot/></template>',
|
||||||
)
|
)
|
||||||
expect(
|
expect(
|
||||||
assertSharedCodegen(codegenNode, false, true /* custom return */)
|
assertSharedCodegen(codegenNode, false, true /* custom return */),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
params: [{ content: `item` }],
|
params: [{ content: `item` }],
|
||||||
returns: {
|
returns: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT
|
callee: RENDER_SLOT,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -850,9 +852,9 @@ describe('compiler: v-for', () => {
|
||||||
test('template v-for key injection with single child', () => {
|
test('template v-for key injection with single child', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(
|
} = parseWithForTransform(
|
||||||
'<template v-for="item in items" :key="item.id"><span :id="item.id" /></template>'
|
'<template v-for="item in items" :key="item.id"><span :id="item.id" /></template>',
|
||||||
)
|
)
|
||||||
expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
|
@ -862,9 +864,9 @@ describe('compiler: v-for', () => {
|
||||||
tag: `"span"`,
|
tag: `"span"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
key: '[item.id]',
|
key: '[item.id]',
|
||||||
id: '[item.id]'
|
id: '[item.id]',
|
||||||
})
|
}),
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -872,17 +874,17 @@ describe('compiler: v-for', () => {
|
||||||
test('v-for on <slot/>', () => {
|
test('v-for on <slot/>', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<slot v-for="item in items"></slot>')
|
} = parseWithForTransform('<slot v-for="item in items"></slot>')
|
||||||
expect(
|
expect(
|
||||||
assertSharedCodegen(codegenNode, false, true /* custom return */)
|
assertSharedCodegen(codegenNode, false, true /* custom return */),
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
params: [{ content: `item` }],
|
params: [{ content: `item` }],
|
||||||
returns: {
|
returns: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT
|
callee: RENDER_SLOT,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -890,7 +892,7 @@ describe('compiler: v-for', () => {
|
||||||
test('keyed v-for', () => {
|
test('keyed v-for', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<span v-for="(item) in items" :key="item" />')
|
} = parseWithForTransform('<span v-for="(item) in items" :key="item" />')
|
||||||
expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
|
@ -898,9 +900,9 @@ describe('compiler: v-for', () => {
|
||||||
innerVNodeCall: {
|
innerVNodeCall: {
|
||||||
tag: `"span"`,
|
tag: `"span"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
key: `[item]`
|
key: `[item]`,
|
||||||
})
|
}),
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -908,9 +910,9 @@ describe('compiler: v-for', () => {
|
||||||
test('keyed template v-for', () => {
|
test('keyed template v-for', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(
|
} = parseWithForTransform(
|
||||||
'<template v-for="item in items" :key="item">hello<span/></template>'
|
'<template v-for="item in items" :key="item">hello<span/></template>',
|
||||||
)
|
)
|
||||||
expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
|
expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
|
||||||
source: { content: `items` },
|
source: { content: `items` },
|
||||||
|
@ -918,14 +920,14 @@ describe('compiler: v-for', () => {
|
||||||
innerVNodeCall: {
|
innerVNodeCall: {
|
||||||
tag: FRAGMENT,
|
tag: FRAGMENT,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
key: `[item]`
|
key: `[item]`,
|
||||||
}),
|
}),
|
||||||
children: [
|
children: [
|
||||||
{ type: NodeTypes.TEXT, content: `hello` },
|
{ type: NodeTypes.TEXT, content: `hello` },
|
||||||
{ type: NodeTypes.ELEMENT, tag: `span` }
|
{ type: NodeTypes.ELEMENT, tag: `span` },
|
||||||
],
|
],
|
||||||
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT)
|
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -933,7 +935,7 @@ describe('compiler: v-for', () => {
|
||||||
test('v-if + v-for', () => {
|
test('v-if + v-for', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(`<div v-if="ok" v-for="i in list"/>`)
|
} = parseWithForTransform(`<div v-if="ok" v-for="i in list"/>`)
|
||||||
expect(codegenNode).toMatchObject({
|
expect(codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
|
@ -941,7 +943,7 @@ describe('compiler: v-for', () => {
|
||||||
consequent: {
|
consequent: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
key: `[0]`
|
key: `[0]`,
|
||||||
}),
|
}),
|
||||||
isBlock: true,
|
isBlock: true,
|
||||||
disableTracking: true,
|
disableTracking: true,
|
||||||
|
@ -957,12 +959,12 @@ describe('compiler: v-for', () => {
|
||||||
returns: {
|
returns: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
isBlock: true
|
isBlock: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -971,7 +973,7 @@ describe('compiler: v-for', () => {
|
||||||
test('v-if + v-for on <template>', () => {
|
test('v-if + v-for on <template>', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform(`<template v-if="ok" v-for="i in list"/>`)
|
} = parseWithForTransform(`<template v-if="ok" v-for="i in list"/>`)
|
||||||
expect(codegenNode).toMatchObject({
|
expect(codegenNode).toMatchObject({
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
|
@ -979,7 +981,7 @@ describe('compiler: v-for', () => {
|
||||||
consequent: {
|
consequent: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
key: `[0]`
|
key: `[0]`,
|
||||||
}),
|
}),
|
||||||
isBlock: true,
|
isBlock: true,
|
||||||
disableTracking: true,
|
disableTracking: true,
|
||||||
|
@ -995,12 +997,12 @@ describe('compiler: v-for', () => {
|
||||||
returns: {
|
returns: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: FRAGMENT,
|
tag: FRAGMENT,
|
||||||
isBlock: true
|
isBlock: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -1008,12 +1010,12 @@ describe('compiler: v-for', () => {
|
||||||
test('v-for on element with custom directive', () => {
|
test('v-for on element with custom directive', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithForTransform('<div v-for="i in list" v-foo/>')
|
} = parseWithForTransform('<div v-for="i in list" v-foo/>')
|
||||||
const { returns } = assertSharedCodegen(codegenNode, false, true)
|
const { returns } = assertSharedCodegen(codegenNode, false, true)
|
||||||
expect(returns).toMatchObject({
|
expect(returns).toMatchObject({
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION }
|
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION },
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,26 +4,26 @@ import { transformIf } from '../../src/transforms/vIf'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||||
import {
|
import {
|
||||||
CommentNode,
|
type CommentNode,
|
||||||
ConditionalExpression,
|
type ConditionalExpression,
|
||||||
ElementNode,
|
type ElementNode,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
IfBranchNode,
|
type IfBranchNode,
|
||||||
IfConditionalExpression,
|
type IfConditionalExpression,
|
||||||
IfNode,
|
type IfNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
SimpleExpressionNode,
|
type SimpleExpressionNode,
|
||||||
TextNode,
|
type TextNode,
|
||||||
VNodeCall
|
type VNodeCall,
|
||||||
} from '../../src/ast'
|
} from '../../src/ast'
|
||||||
import { ErrorCodes } from '../../src/errors'
|
import { ErrorCodes } from '../../src/errors'
|
||||||
import { CompilerOptions, generate, TO_HANDLERS } from '../../src'
|
import { type CompilerOptions, TO_HANDLERS, generate } from '../../src'
|
||||||
import {
|
import {
|
||||||
CREATE_COMMENT,
|
CREATE_COMMENT,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
MERGE_PROPS,
|
MERGE_PROPS,
|
||||||
NORMALIZE_PROPS,
|
NORMALIZE_PROPS,
|
||||||
RENDER_SLOT
|
RENDER_SLOT,
|
||||||
} from '../../src/runtimeHelpers'
|
} from '../../src/runtimeHelpers'
|
||||||
import { createObjectMatcher } from '../testUtils'
|
import { createObjectMatcher } from '../testUtils'
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@ function parseWithIfTransform(
|
||||||
template: string,
|
template: string,
|
||||||
options: CompilerOptions = {},
|
options: CompilerOptions = {},
|
||||||
returnIndex: number = 0,
|
returnIndex: number = 0,
|
||||||
childrenLen: number = 1
|
childrenLen: number = 1,
|
||||||
) {
|
) {
|
||||||
const ast = parse(template, options)
|
const ast = parse(template, options)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformIf, transformSlotOutlet, transformElement],
|
nodeTransforms: [transformIf, transformSlotOutlet, transformElement],
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
if (!options.onError) {
|
if (!options.onError) {
|
||||||
expect(ast.children.length).toBe(childrenLen)
|
expect(ast.children.length).toBe(childrenLen)
|
||||||
|
@ -48,7 +48,7 @@ function parseWithIfTransform(
|
||||||
root: ast,
|
root: ast,
|
||||||
node: ast.children[returnIndex] as IfNode & {
|
node: ast.children[returnIndex] as IfNode & {
|
||||||
codegenNode: IfConditionalExpression
|
codegenNode: IfConditionalExpression
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ describe('compiler: v-if', () => {
|
||||||
expect(node.type).toBe(NodeTypes.IF)
|
expect(node.type).toBe(NodeTypes.IF)
|
||||||
expect(node.branches.length).toBe(1)
|
expect(node.branches.length).toBe(1)
|
||||||
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
|
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
|
||||||
`ok`
|
`ok`,
|
||||||
)
|
)
|
||||||
expect(node.branches[0].children.length).toBe(1)
|
expect(node.branches[0].children.length).toBe(1)
|
||||||
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
|
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
|
||||||
|
@ -68,12 +68,12 @@ describe('compiler: v-if', () => {
|
||||||
|
|
||||||
test('template v-if', () => {
|
test('template v-if', () => {
|
||||||
const { node } = parseWithIfTransform(
|
const { node } = parseWithIfTransform(
|
||||||
`<template v-if="ok"><div/>hello<p/></template>`
|
`<template v-if="ok"><div/>hello<p/></template>`,
|
||||||
)
|
)
|
||||||
expect(node.type).toBe(NodeTypes.IF)
|
expect(node.type).toBe(NodeTypes.IF)
|
||||||
expect(node.branches.length).toBe(1)
|
expect(node.branches.length).toBe(1)
|
||||||
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
|
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
|
||||||
`ok`
|
`ok`,
|
||||||
)
|
)
|
||||||
expect(node.branches[0].children.length).toBe(3)
|
expect(node.branches[0].children.length).toBe(3)
|
||||||
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
|
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
|
||||||
|
@ -89,16 +89,16 @@ describe('compiler: v-if', () => {
|
||||||
expect(node.type).toBe(NodeTypes.IF)
|
expect(node.type).toBe(NodeTypes.IF)
|
||||||
expect(node.branches.length).toBe(1)
|
expect(node.branches.length).toBe(1)
|
||||||
expect((node.branches[0].children[0] as ElementNode).tag).toBe(
|
expect((node.branches[0].children[0] as ElementNode).tag).toBe(
|
||||||
`Component`
|
`Component`,
|
||||||
)
|
)
|
||||||
expect((node.branches[0].children[0] as ElementNode).tagType).toBe(
|
expect((node.branches[0].children[0] as ElementNode).tagType).toBe(
|
||||||
ElementTypes.COMPONENT
|
ElementTypes.COMPONENT,
|
||||||
)
|
)
|
||||||
// #2058 since a component may fail to resolve and fallback to a plain
|
// #2058 since a component may fail to resolve and fallback to a plain
|
||||||
// element, it still needs to be made a block
|
// element, it still needs to be made a block
|
||||||
expect(
|
expect(
|
||||||
((node.branches[0].children[0] as ElementNode)!
|
((node.branches[0].children[0] as ElementNode)!
|
||||||
.codegenNode as VNodeCall)!.isBlock
|
.codegenNode as VNodeCall)!.isBlock,
|
||||||
).toBe(true)
|
).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ describe('compiler: v-if', () => {
|
||||||
|
|
||||||
test('v-if + v-else-if', () => {
|
test('v-if + v-else-if', () => {
|
||||||
const { node } = parseWithIfTransform(
|
const { node } = parseWithIfTransform(
|
||||||
`<div v-if="ok"/><p v-else-if="orNot"/>`
|
`<div v-if="ok"/><p v-else-if="orNot"/>`,
|
||||||
)
|
)
|
||||||
expect(node.type).toBe(NodeTypes.IF)
|
expect(node.type).toBe(NodeTypes.IF)
|
||||||
expect(node.branches.length).toBe(2)
|
expect(node.branches.length).toBe(2)
|
||||||
|
@ -142,7 +142,7 @@ describe('compiler: v-if', () => {
|
||||||
|
|
||||||
test('v-if + v-else-if + v-else', () => {
|
test('v-if + v-else-if + v-else', () => {
|
||||||
const { node } = parseWithIfTransform(
|
const { node } = parseWithIfTransform(
|
||||||
`<div v-if="ok"/><p v-else-if="orNot"/><template v-else>fine</template>`
|
`<div v-if="ok"/><p v-else-if="orNot"/><template v-else>fine</template>`,
|
||||||
)
|
)
|
||||||
expect(node.type).toBe(NodeTypes.IF)
|
expect(node.type).toBe(NodeTypes.IF)
|
||||||
expect(node.branches.length).toBe(3)
|
expect(node.branches.length).toBe(3)
|
||||||
|
@ -202,11 +202,11 @@ describe('compiler: v-if', () => {
|
||||||
|
|
||||||
test('should prefix v-if condition', () => {
|
test('should prefix v-if condition', () => {
|
||||||
const { node } = parseWithIfTransform(`<div v-if="ok"/>`, {
|
const { node } = parseWithIfTransform(`<div v-if="ok"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(node.branches[0].condition).toMatchObject({
|
expect(node.branches[0].condition).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.ok`
|
content: `_ctx.ok`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -219,32 +219,32 @@ describe('compiler: v-if', () => {
|
||||||
expect(onError.mock.calls[0]).toMatchObject([
|
expect(onError.mock.calls[0]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||||
loc: node1.loc
|
loc: node1.loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const { node: node2 } = parseWithIfTransform(
|
const { node: node2 } = parseWithIfTransform(
|
||||||
`<div/><div v-else/>`,
|
`<div/><div v-else/>`,
|
||||||
{ onError },
|
{ onError },
|
||||||
1
|
1,
|
||||||
)
|
)
|
||||||
expect(onError.mock.calls[1]).toMatchObject([
|
expect(onError.mock.calls[1]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||||
loc: node2.loc
|
loc: node2.loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const { node: node3 } = parseWithIfTransform(
|
const { node: node3 } = parseWithIfTransform(
|
||||||
`<div/>foo<div v-else/>`,
|
`<div/>foo<div v-else/>`,
|
||||||
{ onError },
|
{ onError },
|
||||||
2
|
2,
|
||||||
)
|
)
|
||||||
expect(onError.mock.calls[2]).toMatchObject([
|
expect(onError.mock.calls[2]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||||
loc: node3.loc
|
loc: node3.loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -252,52 +252,52 @@ describe('compiler: v-if', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
|
|
||||||
const { node: node1 } = parseWithIfTransform(`<div v-else-if="foo"/>`, {
|
const { node: node1 } = parseWithIfTransform(`<div v-else-if="foo"/>`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError.mock.calls[0]).toMatchObject([
|
expect(onError.mock.calls[0]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||||
loc: node1.loc
|
loc: node1.loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const { node: node2 } = parseWithIfTransform(
|
const { node: node2 } = parseWithIfTransform(
|
||||||
`<div/><div v-else-if="foo"/>`,
|
`<div/><div v-else-if="foo"/>`,
|
||||||
{ onError },
|
{ onError },
|
||||||
1
|
1,
|
||||||
)
|
)
|
||||||
expect(onError.mock.calls[1]).toMatchObject([
|
expect(onError.mock.calls[1]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||||
loc: node2.loc
|
loc: node2.loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const { node: node3 } = parseWithIfTransform(
|
const { node: node3 } = parseWithIfTransform(
|
||||||
`<div/>foo<div v-else-if="foo"/>`,
|
`<div/>foo<div v-else-if="foo"/>`,
|
||||||
{ onError },
|
{ onError },
|
||||||
2
|
2,
|
||||||
)
|
)
|
||||||
expect(onError.mock.calls[2]).toMatchObject([
|
expect(onError.mock.calls[2]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||||
loc: node3.loc
|
loc: node3.loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const {
|
const {
|
||||||
node: { branches }
|
node: { branches },
|
||||||
} = parseWithIfTransform(
|
} = parseWithIfTransform(
|
||||||
`<div v-if="notOk"/><div v-else/><div v-else-if="ok"/>`,
|
`<div v-if="notOk"/><div v-else/><div v-else-if="ok"/>`,
|
||||||
{ onError },
|
{ onError },
|
||||||
0
|
0,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(onError.mock.calls[3]).toMatchObject([
|
expect(onError.mock.calls[3]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||||
loc: branches[branches.length - 1].loc
|
loc: branches[branches.length - 1].loc,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -306,21 +306,21 @@ describe('compiler: v-if', () => {
|
||||||
// dynamic
|
// dynamic
|
||||||
parseWithIfTransform(
|
parseWithIfTransform(
|
||||||
`<div v-if="ok" :key="a + 1" /><div v-else :key="a + 1" />`,
|
`<div v-if="ok" :key="a + 1" /><div v-else :key="a + 1" />`,
|
||||||
{ onError }
|
{ onError },
|
||||||
)
|
)
|
||||||
expect(onError.mock.calls[0]).toMatchObject([
|
expect(onError.mock.calls[0]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_IF_SAME_KEY
|
code: ErrorCodes.X_V_IF_SAME_KEY,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
// static
|
// static
|
||||||
parseWithIfTransform(`<div v-if="ok" key="1" /><div v-else key="1" />`, {
|
parseWithIfTransform(`<div v-if="ok" key="1" /><div v-else key="1" />`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError.mock.calls[1]).toMatchObject([
|
expect(onError.mock.calls[1]).toMatchObject([
|
||||||
{
|
{
|
||||||
code: ErrorCodes.X_V_IF_SAME_KEY
|
code: ErrorCodes.X_V_IF_SAME_KEY,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -329,63 +329,63 @@ describe('compiler: v-if', () => {
|
||||||
function assertSharedCodegen(
|
function assertSharedCodegen(
|
||||||
node: IfConditionalExpression,
|
node: IfConditionalExpression,
|
||||||
depth: number = 0,
|
depth: number = 0,
|
||||||
hasElse: boolean = false
|
hasElse: boolean = false,
|
||||||
) {
|
) {
|
||||||
expect(node).toMatchObject({
|
expect(node).toMatchObject({
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
test: {
|
test: {
|
||||||
content: `ok`
|
content: `ok`,
|
||||||
},
|
},
|
||||||
consequent: {
|
consequent: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
isBlock: true
|
isBlock: true,
|
||||||
},
|
},
|
||||||
alternate:
|
alternate:
|
||||||
depth < 1
|
depth < 1
|
||||||
? hasElse
|
? hasElse
|
||||||
? {
|
? {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
isBlock: true
|
isBlock: true,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_COMMENT
|
callee: CREATE_COMMENT,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
test: {
|
test: {
|
||||||
content: `orNot`
|
content: `orNot`,
|
||||||
},
|
},
|
||||||
consequent: {
|
consequent: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
isBlock: true
|
isBlock: true,
|
||||||
},
|
},
|
||||||
alternate: hasElse
|
alternate: hasElse
|
||||||
? {
|
? {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
isBlock: true
|
isBlock: true,
|
||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_COMMENT
|
callee: CREATE_COMMENT,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
test('basic v-if', () => {
|
test('basic v-if', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok"/>`)
|
} = parseWithIfTransform(`<div v-if="ok"/>`)
|
||||||
assertSharedCodegen(codegenNode)
|
assertSharedCodegen(codegenNode)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[0]` })
|
props: createObjectMatcher({ key: `[0]` }),
|
||||||
})
|
})
|
||||||
expect(codegenNode.alternate).toMatchObject({
|
expect(codegenNode.alternate).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_COMMENT
|
callee: CREATE_COMMENT,
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -393,7 +393,7 @@ describe('compiler: v-if', () => {
|
||||||
test('template v-if', () => {
|
test('template v-if', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<template v-if="ok"><div/>hello<p/></template>`)
|
} = parseWithIfTransform(`<template v-if="ok"><div/>hello<p/></template>`)
|
||||||
assertSharedCodegen(codegenNode)
|
assertSharedCodegen(codegenNode)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
|
@ -402,12 +402,12 @@ describe('compiler: v-if', () => {
|
||||||
children: [
|
children: [
|
||||||
{ type: NodeTypes.ELEMENT, tag: 'div' },
|
{ type: NodeTypes.ELEMENT, tag: 'div' },
|
||||||
{ type: NodeTypes.TEXT, content: `hello` },
|
{ type: NodeTypes.TEXT, content: `hello` },
|
||||||
{ type: NodeTypes.ELEMENT, tag: 'p' }
|
{ type: NodeTypes.ELEMENT, tag: 'p' },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect(codegenNode.alternate).toMatchObject({
|
expect(codegenNode.alternate).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_COMMENT
|
callee: CREATE_COMMENT,
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -415,12 +415,12 @@ describe('compiler: v-if', () => {
|
||||||
test('template v-if w/ single <slot/> child', () => {
|
test('template v-if w/ single <slot/> child', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<template v-if="ok"><slot/></template>`)
|
} = parseWithIfTransform(`<template v-if="ok"><slot/></template>`)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT,
|
callee: RENDER_SLOT,
|
||||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
|
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -428,12 +428,12 @@ describe('compiler: v-if', () => {
|
||||||
test('v-if on <slot/>', () => {
|
test('v-if on <slot/>', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<slot v-if="ok"></slot>`)
|
} = parseWithIfTransform(`<slot v-if="ok"></slot>`)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT,
|
callee: RENDER_SLOT,
|
||||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
|
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -441,16 +441,16 @@ describe('compiler: v-if', () => {
|
||||||
test('v-if + v-else', () => {
|
test('v-if + v-else', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok"/><p v-else/>`)
|
} = parseWithIfTransform(`<div v-if="ok"/><p v-else/>`)
|
||||||
assertSharedCodegen(codegenNode, 0, true)
|
assertSharedCodegen(codegenNode, 0, true)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[0]` })
|
props: createObjectMatcher({ key: `[0]` }),
|
||||||
})
|
})
|
||||||
expect(codegenNode.alternate).toMatchObject({
|
expect(codegenNode.alternate).toMatchObject({
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
props: createObjectMatcher({ key: `[1]` })
|
props: createObjectMatcher({ key: `[1]` }),
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -458,17 +458,17 @@ describe('compiler: v-if', () => {
|
||||||
test('v-if + v-else-if', () => {
|
test('v-if + v-else-if', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok"/><p v-else-if="orNot" />`)
|
} = parseWithIfTransform(`<div v-if="ok"/><p v-else-if="orNot" />`)
|
||||||
assertSharedCodegen(codegenNode, 1)
|
assertSharedCodegen(codegenNode, 1)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[0]` })
|
props: createObjectMatcher({ key: `[0]` }),
|
||||||
})
|
})
|
||||||
const branch2 = codegenNode.alternate as ConditionalExpression
|
const branch2 = codegenNode.alternate as ConditionalExpression
|
||||||
expect(branch2.consequent).toMatchObject({
|
expect(branch2.consequent).toMatchObject({
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
props: createObjectMatcher({ key: `[1]` })
|
props: createObjectMatcher({ key: `[1]` }),
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -476,19 +476,19 @@ describe('compiler: v-if', () => {
|
||||||
test('v-if + v-else-if + v-else', () => {
|
test('v-if + v-else-if + v-else', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(
|
} = parseWithIfTransform(
|
||||||
`<div v-if="ok"/><p v-else-if="orNot"/><template v-else>fine</template>`
|
`<div v-if="ok"/><p v-else-if="orNot"/><template v-else>fine</template>`,
|
||||||
)
|
)
|
||||||
assertSharedCodegen(codegenNode, 1, true)
|
assertSharedCodegen(codegenNode, 1, true)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[0]` })
|
props: createObjectMatcher({ key: `[0]` }),
|
||||||
})
|
})
|
||||||
const branch2 = codegenNode.alternate as ConditionalExpression
|
const branch2 = codegenNode.alternate as ConditionalExpression
|
||||||
expect(branch2.consequent).toMatchObject({
|
expect(branch2.consequent).toMatchObject({
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
props: createObjectMatcher({ key: `[1]` })
|
props: createObjectMatcher({ key: `[1]` }),
|
||||||
})
|
})
|
||||||
expect(branch2.alternate).toMatchObject({
|
expect(branch2.alternate).toMatchObject({
|
||||||
tag: FRAGMENT,
|
tag: FRAGMENT,
|
||||||
|
@ -496,9 +496,9 @@ describe('compiler: v-if', () => {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `fine`
|
content: `fine`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -508,7 +508,7 @@ describe('compiler: v-if', () => {
|
||||||
`<div v-if="ok"/><p v-if="orNot"/>`,
|
`<div v-if="ok"/><p v-if="orNot"/>`,
|
||||||
{},
|
{},
|
||||||
0 /* returnIndex, just give the default value */,
|
0 /* returnIndex, just give the default value */,
|
||||||
2 /* childrenLen */
|
2 /* childrenLen */,
|
||||||
)
|
)
|
||||||
|
|
||||||
const ifNode = root.children[0] as IfNode & {
|
const ifNode = root.children[0] as IfNode & {
|
||||||
|
@ -516,14 +516,14 @@ describe('compiler: v-if', () => {
|
||||||
}
|
}
|
||||||
expect(ifNode.codegenNode.consequent).toMatchObject({
|
expect(ifNode.codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[0]` })
|
props: createObjectMatcher({ key: `[0]` }),
|
||||||
})
|
})
|
||||||
const ifNode2 = root.children[1] as IfNode & {
|
const ifNode2 = root.children[1] as IfNode & {
|
||||||
codegenNode: IfConditionalExpression
|
codegenNode: IfConditionalExpression
|
||||||
}
|
}
|
||||||
expect(ifNode2.codegenNode.consequent).toMatchObject({
|
expect(ifNode2.codegenNode.consequent).toMatchObject({
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
props: createObjectMatcher({ key: `[1]` })
|
props: createObjectMatcher({ key: `[1]` }),
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -533,41 +533,41 @@ describe('compiler: v-if', () => {
|
||||||
`<div v-if="ok"/><p v-else/><div v-if="another"/><p v-else-if="orNot"/><p v-else/>`,
|
`<div v-if="ok"/><p v-else/><div v-if="another"/><p v-else-if="orNot"/><p v-else/>`,
|
||||||
{},
|
{},
|
||||||
0 /* returnIndex, just give the default value */,
|
0 /* returnIndex, just give the default value */,
|
||||||
2 /* childrenLen */
|
2 /* childrenLen */,
|
||||||
)
|
)
|
||||||
const ifNode = root.children[0] as IfNode & {
|
const ifNode = root.children[0] as IfNode & {
|
||||||
codegenNode: IfConditionalExpression
|
codegenNode: IfConditionalExpression
|
||||||
}
|
}
|
||||||
expect(ifNode.codegenNode.consequent).toMatchObject({
|
expect(ifNode.codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[0]` })
|
props: createObjectMatcher({ key: `[0]` }),
|
||||||
})
|
})
|
||||||
expect(ifNode.codegenNode.alternate).toMatchObject({
|
expect(ifNode.codegenNode.alternate).toMatchObject({
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
props: createObjectMatcher({ key: `[1]` })
|
props: createObjectMatcher({ key: `[1]` }),
|
||||||
})
|
})
|
||||||
const ifNode2 = root.children[1] as IfNode & {
|
const ifNode2 = root.children[1] as IfNode & {
|
||||||
codegenNode: IfConditionalExpression
|
codegenNode: IfConditionalExpression
|
||||||
}
|
}
|
||||||
expect(ifNode2.codegenNode.consequent).toMatchObject({
|
expect(ifNode2.codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[2]` })
|
props: createObjectMatcher({ key: `[2]` }),
|
||||||
})
|
})
|
||||||
const branch = ifNode2.codegenNode.alternate as IfConditionalExpression
|
const branch = ifNode2.codegenNode.alternate as IfConditionalExpression
|
||||||
expect(branch.consequent).toMatchObject({
|
expect(branch.consequent).toMatchObject({
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
props: createObjectMatcher({ key: `[3]` })
|
props: createObjectMatcher({ key: `[3]` }),
|
||||||
})
|
})
|
||||||
expect(branch.alternate).toMatchObject({
|
expect(branch.alternate).toMatchObject({
|
||||||
tag: `"p"`,
|
tag: `"p"`,
|
||||||
props: createObjectMatcher({ key: `[4]` })
|
props: createObjectMatcher({ key: `[4]` }),
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('key injection (only v-bind)', () => {
|
test('key injection (only v-bind)', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok" v-bind="obj"/>`)
|
} = parseWithIfTransform(`<div v-if="ok" v-bind="obj"/>`)
|
||||||
const branch1 = codegenNode.consequent as VNodeCall
|
const branch1 = codegenNode.consequent as VNodeCall
|
||||||
expect(branch1.props).toMatchObject({
|
expect(branch1.props).toMatchObject({
|
||||||
|
@ -577,15 +577,18 @@ describe('compiler: v-if', () => {
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: MERGE_PROPS,
|
callee: MERGE_PROPS,
|
||||||
arguments: [createObjectMatcher({ key: `[0]` }), { content: `obj` }]
|
arguments: [
|
||||||
}
|
createObjectMatcher({ key: `[0]` }),
|
||||||
]
|
{ content: `obj` },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('key injection (before v-bind)', () => {
|
test('key injection (before v-bind)', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok" id="foo" v-bind="obj"/>`)
|
} = parseWithIfTransform(`<div v-if="ok" id="foo" v-bind="obj"/>`)
|
||||||
const branch1 = codegenNode.consequent as VNodeCall
|
const branch1 = codegenNode.consequent as VNodeCall
|
||||||
expect(branch1.props).toMatchObject({
|
expect(branch1.props).toMatchObject({
|
||||||
|
@ -594,16 +597,16 @@ describe('compiler: v-if', () => {
|
||||||
arguments: [
|
arguments: [
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
key: '[0]',
|
key: '[0]',
|
||||||
id: 'foo'
|
id: 'foo',
|
||||||
}),
|
}),
|
||||||
{ content: `obj` }
|
{ content: `obj` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('key injection (after v-bind)', () => {
|
test('key injection (after v-bind)', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok" v-bind="obj" id="foo"/>`)
|
} = parseWithIfTransform(`<div v-if="ok" v-bind="obj" id="foo"/>`)
|
||||||
const branch1 = codegenNode.consequent as VNodeCall
|
const branch1 = codegenNode.consequent as VNodeCall
|
||||||
expect(branch1.props).toMatchObject({
|
expect(branch1.props).toMatchObject({
|
||||||
|
@ -613,15 +616,15 @@ describe('compiler: v-if', () => {
|
||||||
createObjectMatcher({ key: `[0]` }),
|
createObjectMatcher({ key: `[0]` }),
|
||||||
{ content: `obj` },
|
{ content: `obj` },
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
id: 'foo'
|
id: 'foo',
|
||||||
})
|
}),
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('key injection (w/ custom directive)', () => {
|
test('key injection (w/ custom directive)', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok" v-foo />`)
|
} = parseWithIfTransform(`<div v-if="ok" v-foo />`)
|
||||||
const branch1 = codegenNode.consequent as VNodeCall
|
const branch1 = codegenNode.consequent as VNodeCall
|
||||||
expect(branch1.directives).not.toBeUndefined()
|
expect(branch1.directives).not.toBeUndefined()
|
||||||
|
@ -631,7 +634,7 @@ describe('compiler: v-if', () => {
|
||||||
// #6631
|
// #6631
|
||||||
test('avoid duplicate keys', () => {
|
test('avoid duplicate keys', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(`<div v-if="ok" key="custom_key" v-bind="obj"/>`)
|
} = parseWithIfTransform(`<div v-if="ok" key="custom_key" v-bind="obj"/>`)
|
||||||
const branch1 = codegenNode.consequent as VNodeCall
|
const branch1 = codegenNode.consequent as VNodeCall
|
||||||
expect(branch1.props).toMatchObject({
|
expect(branch1.props).toMatchObject({
|
||||||
|
@ -639,31 +642,31 @@ describe('compiler: v-if', () => {
|
||||||
callee: MERGE_PROPS,
|
callee: MERGE_PROPS,
|
||||||
arguments: [
|
arguments: [
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
key: 'custom_key'
|
key: 'custom_key',
|
||||||
}),
|
}),
|
||||||
{ content: `obj` }
|
{ content: `obj` },
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('with spaces between branches', () => {
|
test('with spaces between branches', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(
|
} = parseWithIfTransform(
|
||||||
`<div v-if="ok"/> <div v-else-if="no"/> <div v-else/>`
|
`<div v-if="ok"/> <div v-else-if="no"/> <div v-else/>`,
|
||||||
)
|
)
|
||||||
expect(codegenNode.consequent).toMatchObject({
|
expect(codegenNode.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[0]` })
|
props: createObjectMatcher({ key: `[0]` }),
|
||||||
})
|
})
|
||||||
const branch = codegenNode.alternate as ConditionalExpression
|
const branch = codegenNode.alternate as ConditionalExpression
|
||||||
expect(branch.consequent).toMatchObject({
|
expect(branch.consequent).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[1]` })
|
props: createObjectMatcher({ key: `[1]` }),
|
||||||
})
|
})
|
||||||
expect(branch.alternate).toMatchObject({
|
expect(branch.alternate).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({ key: `[2]` })
|
props: createObjectMatcher({ key: `[2]` }),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -729,7 +732,7 @@ describe('compiler: v-if', () => {
|
||||||
<p/>
|
<p/>
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ comments: true }
|
{ comments: true },
|
||||||
)
|
)
|
||||||
__DEV__ = true
|
__DEV__ = true
|
||||||
})
|
})
|
||||||
|
@ -737,21 +740,21 @@ describe('compiler: v-if', () => {
|
||||||
|
|
||||||
test('v-on with v-if', () => {
|
test('v-on with v-if', () => {
|
||||||
const {
|
const {
|
||||||
node: { codegenNode }
|
node: { codegenNode },
|
||||||
} = parseWithIfTransform(
|
} = parseWithIfTransform(
|
||||||
`<button v-on="{ click: clickEvent }" v-if="true">w/ v-if</button>`
|
`<button v-on="{ click: clickEvent }" v-if="true">w/ v-if</button>`,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect((codegenNode.consequent as any).props.type).toBe(
|
expect((codegenNode.consequent as any).props.type).toBe(
|
||||||
NodeTypes.JS_CALL_EXPRESSION
|
NodeTypes.JS_CALL_EXPRESSION,
|
||||||
)
|
)
|
||||||
expect((codegenNode.consequent as any).props.callee).toBe(MERGE_PROPS)
|
expect((codegenNode.consequent as any).props.callee).toBe(MERGE_PROPS)
|
||||||
expect(
|
expect(
|
||||||
(codegenNode.consequent as any).props.arguments[0].properties[0].value
|
(codegenNode.consequent as any).props.arguments[0].properties[0].value
|
||||||
.content
|
.content,
|
||||||
).toBe('0')
|
).toBe('0')
|
||||||
expect((codegenNode.consequent as any).props.arguments[1].callee).toBe(
|
expect((codegenNode.consequent as any).props.arguments[1].callee).toBe(
|
||||||
TO_HANDLERS
|
TO_HANDLERS,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe('compiler: v-memo transform', () => {
|
||||||
function compile(content: string) {
|
function compile(content: string) {
|
||||||
return baseCompile(`<div>${content}</div>`, {
|
return baseCompile(`<div>${content}</div>`, {
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}).code
|
}).code
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ describe('compiler: v-memo transform', () => {
|
||||||
expect(
|
expect(
|
||||||
baseCompile(`<div v-memo="[x]"></div>`, {
|
baseCompile(`<div v-memo="[x]"></div>`, {
|
||||||
mode: 'module',
|
mode: 'module',
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}).code
|
}).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -29,8 +29,8 @@ describe('compiler: v-memo transform', () => {
|
||||||
expect(
|
expect(
|
||||||
compile(
|
compile(
|
||||||
`<div v-if="ok" v-memo="[x]"><span>foo</span>bar</div>
|
`<div v-if="ok" v-memo="[x]"><span>foo</span>bar</div>
|
||||||
<Comp v-else v-memo="[x]"></Comp>`
|
<Comp v-else v-memo="[x]"></Comp>`,
|
||||||
)
|
),
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ describe('compiler: v-memo transform', () => {
|
||||||
compile(
|
compile(
|
||||||
`<div v-for="{ x, y } in list" :key="x" v-memo="[x, y === z]">
|
`<div v-for="{ x, y } in list" :key="x" v-memo="[x, y === z]">
|
||||||
<span>foobar</span>
|
<span>foobar</span>
|
||||||
</div>`
|
</div>`,
|
||||||
)
|
),
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -49,8 +49,8 @@ describe('compiler: v-memo transform', () => {
|
||||||
compile(
|
compile(
|
||||||
`<template v-for="{ x, y } in list" :key="x" v-memo="[x, y === z]">
|
`<template v-for="{ x, y } in list" :key="x" v-memo="[x, y === z]">
|
||||||
<span>foobar</span>
|
<span>foobar</span>
|
||||||
</template>`
|
</template>`,
|
||||||
)
|
),
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import {
|
import {
|
||||||
|
BindingTypes,
|
||||||
|
type CompilerOptions,
|
||||||
|
type ComponentNode,
|
||||||
|
type ElementNode,
|
||||||
|
type ForNode,
|
||||||
|
NORMALIZE_PROPS,
|
||||||
|
NodeTypes,
|
||||||
|
type ObjectExpression,
|
||||||
|
type PlainElementNode,
|
||||||
|
type VNodeCall,
|
||||||
|
generate,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
generate,
|
|
||||||
ElementNode,
|
|
||||||
ObjectExpression,
|
|
||||||
CompilerOptions,
|
|
||||||
ForNode,
|
|
||||||
PlainElementNode,
|
|
||||||
ComponentNode,
|
|
||||||
NodeTypes,
|
|
||||||
VNodeCall,
|
|
||||||
NORMALIZE_PROPS,
|
|
||||||
BindingTypes
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { ErrorCodes } from '../../src/errors'
|
import { ErrorCodes } from '../../src/errors'
|
||||||
import { transformModel } from '../../src/transforms/vModel'
|
import { transformModel } from '../../src/transforms/vModel'
|
||||||
|
@ -19,7 +19,7 @@ import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
import { transformFor } from '../../src/transforms/vFor'
|
import { transformFor } from '../../src/transforms/vFor'
|
||||||
import { trackSlotScopes } from '../../src/transforms/vSlot'
|
import { trackSlotScopes } from '../../src/transforms/vSlot'
|
||||||
import { CallExpression } from '@babel/types'
|
import type { CallExpression } from '@babel/types'
|
||||||
|
|
||||||
function parseWithVModel(template: string, options: CompilerOptions = {}) {
|
function parseWithVModel(template: string, options: CompilerOptions = {}) {
|
||||||
const ast = parse(template)
|
const ast = parse(template)
|
||||||
|
@ -29,13 +29,13 @@ function parseWithVModel(template: string, options: CompilerOptions = {}) {
|
||||||
transformFor,
|
transformFor,
|
||||||
transformExpression,
|
transformExpression,
|
||||||
transformElement,
|
transformElement,
|
||||||
trackSlotScopes
|
trackSlotScopes,
|
||||||
],
|
],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
...options.directiveTransforms,
|
...options.directiveTransforms,
|
||||||
model: transformModel
|
model: transformModel,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
|
|
||||||
return ast
|
return ast
|
||||||
|
@ -51,29 +51,29 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(props[0]).toMatchObject({
|
expect(props[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'modelValue',
|
content: 'modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: 'model',
|
content: 'model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props[1]).toMatchObject({
|
expect(props[1]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'onUpdate:modelValue',
|
content: 'onUpdate:modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
'$event => ((',
|
'$event => ((',
|
||||||
{
|
{
|
||||||
content: 'model',
|
content: 'model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
|
},
|
||||||
|
') = $event)',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
') = $event)'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -81,7 +81,7 @@ describe('compiler: transform v-model', () => {
|
||||||
|
|
||||||
test('simple expression (with prefixIdentifiers)', () => {
|
test('simple expression (with prefixIdentifiers)', () => {
|
||||||
const root = parseWithVModel('<input v-model="model" />', {
|
const root = parseWithVModel('<input v-model="model" />', {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
const node = root.children[0] as ElementNode
|
const node = root.children[0] as ElementNode
|
||||||
const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)
|
const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)
|
||||||
|
@ -90,29 +90,29 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(props[0]).toMatchObject({
|
expect(props[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'modelValue',
|
content: 'modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: '_ctx.model',
|
content: '_ctx.model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props[1]).toMatchObject({
|
expect(props[1]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'onUpdate:modelValue',
|
content: 'onUpdate:modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
'$event => ((',
|
'$event => ((',
|
||||||
{
|
{
|
||||||
content: '_ctx.model',
|
content: '_ctx.model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
|
},
|
||||||
|
') = $event)',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
') = $event)'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
||||||
|
@ -128,29 +128,29 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(props[0]).toMatchObject({
|
expect(props[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'modelValue',
|
content: 'modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: '\n model\n.\nfoo \n',
|
content: '\n model\n.\nfoo \n',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props[1]).toMatchObject({
|
expect(props[1]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'onUpdate:modelValue',
|
content: 'onUpdate:modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
'$event => ((',
|
'$event => ((',
|
||||||
{
|
{
|
||||||
content: '\n model\n.\nfoo \n',
|
content: '\n model\n.\nfoo \n',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
|
},
|
||||||
|
') = $event)',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
') = $event)'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -165,29 +165,29 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(props[0]).toMatchObject({
|
expect(props[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'modelValue',
|
content: 'modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: 'model[index]',
|
content: 'model[index]',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props[1]).toMatchObject({
|
expect(props[1]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'onUpdate:modelValue',
|
content: 'onUpdate:modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
'$event => ((',
|
'$event => ((',
|
||||||
{
|
{
|
||||||
content: 'model[index]',
|
content: 'model[index]',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
|
},
|
||||||
|
') = $event)',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
') = $event)'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -195,7 +195,7 @@ describe('compiler: transform v-model', () => {
|
||||||
|
|
||||||
test('compound expression (with prefixIdentifiers)', () => {
|
test('compound expression (with prefixIdentifiers)', () => {
|
||||||
const root = parseWithVModel('<input v-model="model[index]" />', {
|
const root = parseWithVModel('<input v-model="model[index]" />', {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
const node = root.children[0] as ElementNode
|
const node = root.children[0] as ElementNode
|
||||||
const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)
|
const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)
|
||||||
|
@ -204,28 +204,28 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(props[0]).toMatchObject({
|
expect(props[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'modelValue',
|
content: 'modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
content: '_ctx.model',
|
content: '_ctx.model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
'[',
|
'[',
|
||||||
{
|
{
|
||||||
content: '_ctx.index',
|
content: '_ctx.index',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
|
},
|
||||||
|
']',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
']'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props[1]).toMatchObject({
|
expect(props[1]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'onUpdate:modelValue',
|
content: 'onUpdate:modelValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
|
@ -234,19 +234,19 @@ describe('compiler: transform v-model', () => {
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
content: '_ctx.model',
|
content: '_ctx.model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
'[',
|
'[',
|
||||||
{
|
{
|
||||||
content: '_ctx.index',
|
content: '_ctx.index',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
']'
|
']',
|
||||||
]
|
],
|
||||||
|
},
|
||||||
|
') = $event)',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
') = $event)'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
||||||
|
@ -260,29 +260,29 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(props[0]).toMatchObject({
|
expect(props[0]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'foo-value',
|
content: 'foo-value',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: 'model',
|
content: 'model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props[1]).toMatchObject({
|
expect(props[1]).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: 'onUpdate:fooValue',
|
content: 'onUpdate:fooValue',
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
'$event => ((',
|
'$event => ((',
|
||||||
{
|
{
|
||||||
content: 'model',
|
content: 'model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
|
},
|
||||||
|
') = $event)',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
') = $event)'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -304,12 +304,12 @@ describe('compiler: transform v-model', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: 'value',
|
content: 'value',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: 'model',
|
content: 'model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
|
@ -317,24 +317,24 @@ describe('compiler: transform v-model', () => {
|
||||||
'"onUpdate:" + ',
|
'"onUpdate:" + ',
|
||||||
{
|
{
|
||||||
content: 'value',
|
content: 'value',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
'$event => ((',
|
'$event => ((',
|
||||||
{
|
{
|
||||||
content: 'model',
|
content: 'model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
') = $event)'
|
') = $event)',
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
@ -342,7 +342,7 @@ describe('compiler: transform v-model', () => {
|
||||||
|
|
||||||
test('with dynamic argument (with prefixIdentifiers)', () => {
|
test('with dynamic argument (with prefixIdentifiers)', () => {
|
||||||
const root = parseWithVModel('<input v-model:[value]="model" />', {
|
const root = parseWithVModel('<input v-model:[value]="model" />', {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
const node = root.children[0] as ElementNode
|
const node = root.children[0] as ElementNode
|
||||||
const props = (node.codegenNode as VNodeCall)
|
const props = (node.codegenNode as VNodeCall)
|
||||||
|
@ -358,12 +358,12 @@ describe('compiler: transform v-model', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: '_ctx.value',
|
content: '_ctx.value',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: '_ctx.model',
|
content: '_ctx.model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
|
@ -371,24 +371,24 @@ describe('compiler: transform v-model', () => {
|
||||||
'"onUpdate:" + ',
|
'"onUpdate:" + ',
|
||||||
{
|
{
|
||||||
content: '_ctx.value',
|
content: '_ctx.value',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
children: [
|
children: [
|
||||||
'$event => ((',
|
'$event => ((',
|
||||||
{
|
{
|
||||||
content: '_ctx.model',
|
content: '_ctx.model',
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
},
|
},
|
||||||
') = $event)'
|
') = $event)',
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
||||||
|
@ -397,7 +397,7 @@ describe('compiler: transform v-model', () => {
|
||||||
test('should cache update handler w/ cacheHandlers: true', () => {
|
test('should cache update handler w/ cacheHandlers: true', () => {
|
||||||
const root = parseWithVModel('<input v-model="foo" />', {
|
const root = parseWithVModel('<input v-model="foo" />', {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
const codegen = (root.children[0] as PlainElementNode)
|
const codegen = (root.children[0] as PlainElementNode)
|
||||||
|
@ -405,7 +405,7 @@ describe('compiler: transform v-model', () => {
|
||||||
// should not list cached prop in dynamicProps
|
// should not list cached prop in dynamicProps
|
||||||
expect(codegen.dynamicProps).toBe(`["modelValue"]`)
|
expect(codegen.dynamicProps).toBe(`["modelValue"]`)
|
||||||
expect((codegen.props as ObjectExpression).properties[1].value.type).toBe(
|
expect((codegen.props as ObjectExpression).properties[1].value.type).toBe(
|
||||||
NodeTypes.JS_CACHE_EXPRESSION
|
NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -414,8 +414,8 @@ describe('compiler: transform v-model', () => {
|
||||||
'<input v-for="i in list" v-model="foo[i]" />',
|
'<input v-for="i in list" v-model="foo[i]" />',
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(root.cached).toBe(0)
|
expect(root.cached).toBe(0)
|
||||||
const codegen = (
|
const codegen = (
|
||||||
|
@ -423,14 +423,14 @@ describe('compiler: transform v-model', () => {
|
||||||
).codegenNode as VNodeCall
|
).codegenNode as VNodeCall
|
||||||
expect(codegen.dynamicProps).toBe(`["modelValue", "onUpdate:modelValue"]`)
|
expect(codegen.dynamicProps).toBe(`["modelValue", "onUpdate:modelValue"]`)
|
||||||
expect(
|
expect(
|
||||||
(codegen.props as ObjectExpression).properties[1].value.type
|
(codegen.props as ObjectExpression).properties[1].value.type,
|
||||||
).not.toBe(NodeTypes.JS_CACHE_EXPRESSION)
|
).not.toBe(NodeTypes.JS_CACHE_EXPRESSION)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not cache update handler if it inside v-once', () => {
|
test('should not cache update handler if it inside v-once', () => {
|
||||||
const root = parseWithVModel('<div v-once><input v-model="foo" /></div>', {
|
const root = parseWithVModel('<div v-once><input v-model="foo" /></div>', {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).not.toBe(2)
|
expect(root.cached).not.toBe(2)
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
|
@ -440,8 +440,8 @@ describe('compiler: transform v-model', () => {
|
||||||
const root = parseWithVModel(
|
const root = parseWithVModel(
|
||||||
'<Comp v-slot="{ foo }"><input v-model="foo.bar"/></Comp>',
|
'<Comp v-slot="{ foo }"><input v-model="foo.bar"/></Comp>',
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
const codegen = (
|
const codegen = (
|
||||||
(root.children[0] as ComponentNode).children[0] as PlainElementNode
|
(root.children[0] as ComponentNode).children[0] as PlainElementNode
|
||||||
|
@ -451,7 +451,7 @@ describe('compiler: transform v-model', () => {
|
||||||
|
|
||||||
test('should generate modelModifiers for component v-model', () => {
|
test('should generate modelModifiers for component v-model', () => {
|
||||||
const root = parseWithVModel('<Comp v-model.trim.bar-baz="foo" />', {
|
const root = parseWithVModel('<Comp v-model.trim.bar-baz="foo" />', {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
const vnodeCall = (root.children[0] as ComponentNode)
|
const vnodeCall = (root.children[0] as ComponentNode)
|
||||||
.codegenNode as VNodeCall
|
.codegenNode as VNodeCall
|
||||||
|
@ -462,9 +462,12 @@ describe('compiler: transform v-model', () => {
|
||||||
{ key: { content: `onUpdate:modelValue` } },
|
{ key: { content: `onUpdate:modelValue` } },
|
||||||
{
|
{
|
||||||
key: { content: 'modelModifiers' },
|
key: { content: 'modelModifiers' },
|
||||||
value: { content: `{ trim: true, "bar-baz": true }`, isStatic: false }
|
value: {
|
||||||
}
|
content: `{ trim: true, "bar-baz": true }`,
|
||||||
]
|
isStatic: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
})
|
})
|
||||||
// should NOT include modelModifiers in dynamicPropNames because it's never
|
// should NOT include modelModifiers in dynamicPropNames because it's never
|
||||||
// gonna change
|
// gonna change
|
||||||
|
@ -475,8 +478,8 @@ describe('compiler: transform v-model', () => {
|
||||||
const root = parseWithVModel(
|
const root = parseWithVModel(
|
||||||
'<Comp v-model:foo.trim="foo" v-model:bar.number="bar" />',
|
'<Comp v-model:foo.trim="foo" v-model:bar.number="bar" />',
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
const vnodeCall = (root.children[0] as ComponentNode)
|
const vnodeCall = (root.children[0] as ComponentNode)
|
||||||
.codegenNode as VNodeCall
|
.codegenNode as VNodeCall
|
||||||
|
@ -487,20 +490,20 @@ describe('compiler: transform v-model', () => {
|
||||||
{ key: { content: `onUpdate:foo` } },
|
{ key: { content: `onUpdate:foo` } },
|
||||||
{
|
{
|
||||||
key: { content: 'fooModifiers' },
|
key: { content: 'fooModifiers' },
|
||||||
value: { content: `{ trim: true }`, isStatic: false }
|
value: { content: `{ trim: true }`, isStatic: false },
|
||||||
},
|
},
|
||||||
{ key: { content: `bar` } },
|
{ key: { content: `bar` } },
|
||||||
{ key: { content: `onUpdate:bar` } },
|
{ key: { content: `onUpdate:bar` } },
|
||||||
{
|
{
|
||||||
key: { content: 'barModifiers' },
|
key: { content: 'barModifiers' },
|
||||||
value: { content: `{ number: true }`, isStatic: false }
|
value: { content: `{ number: true }`, isStatic: false },
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
// should NOT include modelModifiers in dynamicPropNames because it's never
|
// should NOT include modelModifiers in dynamicPropNames because it's never
|
||||||
// gonna change
|
// gonna change
|
||||||
expect(vnodeCall.dynamicProps).toBe(
|
expect(vnodeCall.dynamicProps).toBe(
|
||||||
`["foo", "onUpdate:foo", "bar", "onUpdate:bar"]`
|
`["foo", "onUpdate:foo", "bar", "onUpdate:bar"]`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -512,8 +515,8 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_MODEL_NO_EXPRESSION
|
code: ErrorCodes.X_V_MODEL_NO_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -524,8 +527,8 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION
|
code: ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -536,8 +539,8 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION
|
code: ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -552,14 +555,14 @@ describe('compiler: transform v-model', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
parseWithVModel('<span v-for="i in list" v-model="i" />', {
|
parseWithVModel('<span v-for="i in list" v-model="i" />', {
|
||||||
onError,
|
onError,
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE
|
code: ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -568,15 +571,15 @@ describe('compiler: transform v-model', () => {
|
||||||
parseWithVModel('<div v-model="p" />', {
|
parseWithVModel('<div v-model="p" />', {
|
||||||
onError,
|
onError,
|
||||||
bindingMetadata: {
|
bindingMetadata: {
|
||||||
p: BindingTypes.PROPS
|
p: BindingTypes.PROPS,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: ErrorCodes.X_V_MODEL_ON_PROPS
|
code: ErrorCodes.X_V_MODEL_ON_PROPS,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
baseParse as parse,
|
type CompilerOptions,
|
||||||
CompilerOptions,
|
type ElementNode,
|
||||||
ElementNode,
|
|
||||||
ErrorCodes,
|
ErrorCodes,
|
||||||
TO_HANDLER_KEY,
|
|
||||||
helperNameMap,
|
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
ObjectExpression,
|
type ObjectExpression,
|
||||||
|
TO_HANDLER_KEY,
|
||||||
|
type VNodeCall,
|
||||||
|
helperNameMap,
|
||||||
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
VNodeCall
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformOn } from '../../src/transforms/vOn'
|
import { transformOn } from '../../src/transforms/vOn'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
|
@ -19,13 +19,13 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformExpression, transformElement],
|
nodeTransforms: [transformExpression, transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
on: transformOn
|
on: transformOn,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
root: ast,
|
root: ast,
|
||||||
node: ast.children[0] as ElementNode
|
node: ast.children[0] as ElementNode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ describe('compiler: transform v-on', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 11
|
column: 11,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 16
|
column: 16,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `onClick`,
|
content: `onClick`,
|
||||||
|
@ -55,16 +55,16 @@ describe('compiler: transform v-on', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 18
|
column: 18,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 25
|
column: 25,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -78,22 +78,22 @@ describe('compiler: transform v-on', () => {
|
||||||
children: [
|
children: [
|
||||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||||
{ content: `event` },
|
{ content: `event` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `handler`,
|
content: `handler`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('dynamic arg with prefixing', () => {
|
test('dynamic arg with prefixing', () => {
|
||||||
const { node } = parseWithVOn(`<div v-on:[event]="handler"/>`, {
|
const { node } = parseWithVOn(`<div v-on:[event]="handler"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -103,22 +103,22 @@ describe('compiler: transform v-on', () => {
|
||||||
children: [
|
children: [
|
||||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||||
{ content: `_ctx.event` },
|
{ content: `_ctx.event` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.handler`,
|
content: `_ctx.handler`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('dynamic arg with complex exp prefixing', () => {
|
test('dynamic arg with complex exp prefixing', () => {
|
||||||
const { node } = parseWithVOn(`<div v-on:[event(foo)]="handler"/>`, {
|
const { node } = parseWithVOn(`<div v-on:[event(foo)]="handler"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -131,16 +131,16 @@ describe('compiler: transform v-on', () => {
|
||||||
`(`,
|
`(`,
|
||||||
{ content: `_ctx.foo` },
|
{ content: `_ctx.foo` },
|
||||||
`)`,
|
`)`,
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `_ctx.handler`,
|
content: `_ctx.handler`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -152,10 +152,10 @@ describe('compiler: transform v-on', () => {
|
||||||
key: { content: `onClick` },
|
key: { content: `onClick` },
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`$event => (`, { content: `i++` }, `)`]
|
children: [`$event => (`, { content: `i++` }, `)`],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -170,10 +170,10 @@ describe('compiler: transform v-on', () => {
|
||||||
// should wrap with `{` for multiple statements
|
// should wrap with `{` for multiple statements
|
||||||
// in this case the return value is discarded and the behavior is
|
// in this case the return value is discarded and the behavior is
|
||||||
// consistent with 2.x
|
// consistent with 2.x
|
||||||
children: [`$event => {`, { content: `foo();bar()` }, `}`]
|
children: [`$event => {`, { content: `foo();bar()` }, `}`],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -188,16 +188,16 @@ describe('compiler: transform v-on', () => {
|
||||||
// should wrap with `{` for multiple statements
|
// should wrap with `{` for multiple statements
|
||||||
// in this case the return value is discarded and the behavior is
|
// in this case the return value is discarded and the behavior is
|
||||||
// consistent with 2.x
|
// consistent with 2.x
|
||||||
children: [`$event => {`, { content: `\nfoo();\nbar()\n` }, `}`]
|
children: [`$event => {`, { content: `\nfoo();\nbar()\n` }, `}`],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('inline statement w/ prefixIdentifiers: true', () => {
|
test('inline statement w/ prefixIdentifiers: true', () => {
|
||||||
const { node } = parseWithVOn(`<div @click="foo($event)"/>`, {
|
const { node } = parseWithVOn(`<div @click="foo($event)"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -214,20 +214,20 @@ describe('compiler: transform v-on', () => {
|
||||||
`(`,
|
`(`,
|
||||||
// should NOT prefix $event
|
// should NOT prefix $event
|
||||||
{ content: `$event` },
|
{ content: `$event` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('multiple inline statements w/ prefixIdentifiers: true', () => {
|
test('multiple inline statements w/ prefixIdentifiers: true', () => {
|
||||||
const { node } = parseWithVOn(`<div @click="foo($event);bar()"/>`, {
|
const { node } = parseWithVOn(`<div @click="foo($event);bar()"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -245,14 +245,14 @@ describe('compiler: transform v-on', () => {
|
||||||
{ content: `$event` },
|
{ content: `$event` },
|
||||||
`);`,
|
`);`,
|
||||||
{ content: `_ctx.bar` },
|
{ content: `_ctx.bar` },
|
||||||
`()`
|
`()`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
`}`
|
`}`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -264,10 +264,10 @@ describe('compiler: transform v-on', () => {
|
||||||
key: { content: `onClick` },
|
key: { content: `onClick` },
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `$event => foo($event)`
|
content: `$event => foo($event)`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -279,10 +279,10 @@ describe('compiler: transform v-on', () => {
|
||||||
key: { content: `onClick` },
|
key: { content: `onClick` },
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `(e: any): any => foo(e)`
|
content: `(e: any): any => foo(e)`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -292,7 +292,7 @@ describe('compiler: transform v-on', () => {
|
||||||
$event => {
|
$event => {
|
||||||
foo($event)
|
foo($event)
|
||||||
}
|
}
|
||||||
"/>`
|
"/>`,
|
||||||
)
|
)
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -304,10 +304,10 @@ describe('compiler: transform v-on', () => {
|
||||||
$event => {
|
$event => {
|
||||||
foo($event)
|
foo($event)
|
||||||
}
|
}
|
||||||
`
|
`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -317,7 +317,7 @@ describe('compiler: transform v-on', () => {
|
||||||
function($event) {
|
function($event) {
|
||||||
foo($event)
|
foo($event)
|
||||||
}
|
}
|
||||||
"/>`
|
"/>`,
|
||||||
)
|
)
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -329,10 +329,10 @@ describe('compiler: transform v-on', () => {
|
||||||
function($event) {
|
function($event) {
|
||||||
foo($event)
|
foo($event)
|
||||||
}
|
}
|
||||||
`
|
`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -344,16 +344,16 @@ describe('compiler: transform v-on', () => {
|
||||||
key: { content: `onClick` },
|
key: { content: `onClick` },
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `a['b' + c]`
|
content: `a['b' + c]`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('complex member expression w/ prefixIdentifiers: true', () => {
|
test('complex member expression w/ prefixIdentifiers: true', () => {
|
||||||
const { node } = parseWithVOn(`<div @click="a['b' + c]"/>`, {
|
const { node } = parseWithVOn(`<div @click="a['b' + c]"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -365,17 +365,17 @@ describe('compiler: transform v-on', () => {
|
||||||
{ content: `_ctx.a` },
|
{ content: `_ctx.a` },
|
||||||
`['b' + `,
|
`['b' + `,
|
||||||
{ content: `_ctx.c` },
|
{ content: `_ctx.c` },
|
||||||
`]`
|
`]`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('function expression w/ prefixIdentifiers: true', () => {
|
test('function expression w/ prefixIdentifiers: true', () => {
|
||||||
const { node } = parseWithVOn(`<div @click="e => foo(e)"/>`, {
|
const { node } = parseWithVOn(`<div @click="e => foo(e)"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
|
@ -389,11 +389,11 @@ describe('compiler: transform v-on', () => {
|
||||||
{ content: `_ctx.foo` },
|
{ content: `_ctx.foo` },
|
||||||
`(`,
|
`(`,
|
||||||
{ content: `e` },
|
{ content: `e` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -405,13 +405,13 @@ describe('compiler: transform v-on', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 6
|
column: 6,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 16
|
column: 16,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -427,13 +427,13 @@ describe('compiler: transform v-on', () => {
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `onFooBar`
|
content: `onFooBar`,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `onMount`
|
content: `onMount`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -445,39 +445,39 @@ describe('compiler: transform v-on', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: {
|
start: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 11
|
column: 11,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
line: 1,
|
line: 1,
|
||||||
column: 24
|
column: 24,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('vue: prefixed events', () => {
|
test('vue: prefixed events', () => {
|
||||||
const { node } = parseWithVOn(
|
const { node } = parseWithVOn(
|
||||||
`<div v-on:vue:mounted="onMount" @vue:before-update="onBeforeUpdate" />`
|
`<div v-on:vue:mounted="onMount" @vue:before-update="onBeforeUpdate" />`,
|
||||||
)
|
)
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `onVnodeMounted`
|
content: `onVnodeMounted`,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `onMount`
|
content: `onMount`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
content: `onVnodeBeforeUpdate`
|
content: `onVnodeBeforeUpdate`,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
content: `onBeforeUpdate`
|
content: `onBeforeUpdate`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -485,35 +485,35 @@ describe('compiler: transform v-on', () => {
|
||||||
test('empty handler', () => {
|
test('empty handler', () => {
|
||||||
const { root, node } = parseWithVOn(`<div v-on:click.prevent />`, {
|
const { root, node } = parseWithVOn(`<div v-on:click.prevent />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
const vnodeCall = node.codegenNode as VNodeCall
|
const vnodeCall = node.codegenNode as VNodeCall
|
||||||
// should not treat cached handler as dynamicProp, so no flags
|
// should not treat cached handler as dynamicProp, so no flags
|
||||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||||
expect(
|
expect(
|
||||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `() => {}`
|
content: `() => {}`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('member expression handler', () => {
|
test('member expression handler', () => {
|
||||||
const { root, node } = parseWithVOn(`<div v-on:click="foo" />`, {
|
const { root, node } = parseWithVOn(`<div v-on:click="foo" />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
const vnodeCall = node.codegenNode as VNodeCall
|
const vnodeCall = node.codegenNode as VNodeCall
|
||||||
// should not treat cached handler as dynamicProp, so no flags
|
// should not treat cached handler as dynamicProp, so no flags
|
||||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||||
expect(
|
expect(
|
||||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
@ -522,23 +522,23 @@ describe('compiler: transform v-on', () => {
|
||||||
children: [
|
children: [
|
||||||
`(...args) => (`,
|
`(...args) => (`,
|
||||||
{ content: `_ctx.foo && _ctx.foo(...args)` },
|
{ content: `_ctx.foo && _ctx.foo(...args)` },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('compound member expression handler', () => {
|
test('compound member expression handler', () => {
|
||||||
const { root, node } = parseWithVOn(`<div v-on:click="foo.bar" />`, {
|
const { root, node } = parseWithVOn(`<div v-on:click="foo.bar" />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
const vnodeCall = node.codegenNode as VNodeCall
|
const vnodeCall = node.codegenNode as VNodeCall
|
||||||
// should not treat cached handler as dynamicProp, so no flags
|
// should not treat cached handler as dynamicProp, so no flags
|
||||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||||
expect(
|
expect(
|
||||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
@ -555,12 +555,12 @@ describe('compiler: transform v-on', () => {
|
||||||
{ content: `_ctx.foo` },
|
{ content: `_ctx.foo` },
|
||||||
`.`,
|
`.`,
|
||||||
{ content: `bar` },
|
{ content: `bar` },
|
||||||
`(...args)`
|
`(...args)`,
|
||||||
]
|
],
|
||||||
|
},
|
||||||
|
`)`,
|
||||||
|
],
|
||||||
},
|
},
|
||||||
`)`
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -568,7 +568,7 @@ describe('compiler: transform v-on', () => {
|
||||||
const { root } = parseWithVOn(`<comp v-on:click="foo" />`, {
|
const { root } = parseWithVOn(`<comp v-on:click="foo" />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true,
|
cacheHandlers: true,
|
||||||
isNativeTag: tag => tag === 'div'
|
isNativeTag: tag => tag === 'div',
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(0)
|
expect(root.cached).toBe(0)
|
||||||
})
|
})
|
||||||
|
@ -578,8 +578,8 @@ describe('compiler: transform v-on', () => {
|
||||||
`<div v-once><div v-on:click="foo"/></div>`,
|
`<div v-once><div v-on:click="foo"/></div>`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(root.cached).not.toBe(2)
|
expect(root.cached).not.toBe(2)
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
|
@ -588,21 +588,21 @@ describe('compiler: transform v-on', () => {
|
||||||
test('inline function expression handler', () => {
|
test('inline function expression handler', () => {
|
||||||
const { root, node } = parseWithVOn(`<div v-on:click="() => foo()" />`, {
|
const { root, node } = parseWithVOn(`<div v-on:click="() => foo()" />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
const vnodeCall = node.codegenNode as VNodeCall
|
const vnodeCall = node.codegenNode as VNodeCall
|
||||||
// should not treat cached handler as dynamicProp, so no flags
|
// should not treat cached handler as dynamicProp, so no flags
|
||||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||||
expect(
|
expect(
|
||||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`() => `, { content: `_ctx.foo` }, `()`]
|
children: [`() => `, { content: `_ctx.foo` }, `()`],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -611,22 +611,22 @@ describe('compiler: transform v-on', () => {
|
||||||
`<div v-on:click="async () => await foo()" />`,
|
`<div v-on:click="async () => await foo()" />`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
const vnodeCall = node.codegenNode as VNodeCall
|
const vnodeCall = node.codegenNode as VNodeCall
|
||||||
// should not treat cached handler as dynamicProp, so no flags
|
// should not treat cached handler as dynamicProp, so no flags
|
||||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||||
expect(
|
expect(
|
||||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`async () => await `, { content: `_ctx.foo` }, `()`]
|
children: [`async () => await `, { content: `_ctx.foo` }, `()`],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -635,15 +635,15 @@ describe('compiler: transform v-on', () => {
|
||||||
`<div v-on:click="async function () { await foo() } " />`,
|
`<div v-on:click="async function () { await foo() } " />`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
const vnodeCall = node.codegenNode as VNodeCall
|
const vnodeCall = node.codegenNode as VNodeCall
|
||||||
// should not treat cached handler as dynamicProp, so no flags
|
// should not treat cached handler as dynamicProp, so no flags
|
||||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||||
expect(
|
expect(
|
||||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
@ -652,16 +652,16 @@ describe('compiler: transform v-on', () => {
|
||||||
children: [
|
children: [
|
||||||
`async function () { await `,
|
`async function () { await `,
|
||||||
{ content: `_ctx.foo` },
|
{ content: `_ctx.foo` },
|
||||||
`() } `
|
`() } `,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('inline statement handler', () => {
|
test('inline statement handler', () => {
|
||||||
const { root, node } = parseWithVOn(`<div v-on:click="foo++" />`, {
|
const { root, node } = parseWithVOn(`<div v-on:click="foo++" />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
|
@ -669,7 +669,7 @@ describe('compiler: transform v-on', () => {
|
||||||
// should not treat cached handler as dynamicProp, so no flags
|
// should not treat cached handler as dynamicProp, so no flags
|
||||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||||
expect(
|
expect(
|
||||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
|
@ -678,9 +678,9 @@ describe('compiler: transform v-on', () => {
|
||||||
children: [
|
children: [
|
||||||
`$event => (`,
|
`$event => (`,
|
||||||
{ children: [{ content: `_ctx.foo` }, `++`] },
|
{ children: [{ content: `_ctx.foo` }, `++`] },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import {
|
import {
|
||||||
baseParse as parse,
|
type CompilerOptions,
|
||||||
transform,
|
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
generate,
|
generate,
|
||||||
CompilerOptions,
|
getBaseTransformPreset,
|
||||||
getBaseTransformPreset
|
baseParse as parse,
|
||||||
|
transform,
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { RENDER_SLOT, SET_BLOCK_TRACKING } from '../../src/runtimeHelpers'
|
import { RENDER_SLOT, SET_BLOCK_TRACKING } from '../../src/runtimeHelpers'
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ function transformWithOnce(template: string, options: CompilerOptions = {}) {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms,
|
nodeTransforms,
|
||||||
directiveTransforms,
|
directiveTransforms,
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,8 @@ describe('compiler: v-once transform', () => {
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`
|
tag: `"div"`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -44,8 +44,8 @@ describe('compiler: v-once transform', () => {
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`
|
tag: `"div"`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -59,8 +59,8 @@ describe('compiler: v-once transform', () => {
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `_component_Comp`
|
tag: `_component_Comp`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -74,8 +74,8 @@ describe('compiler: v-once transform', () => {
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: RENDER_SLOT
|
callee: RENDER_SLOT,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -90,7 +90,7 @@ describe('compiler: v-once transform', () => {
|
||||||
// cached nodes should be ignored by hoistStatic transform
|
// cached nodes should be ignored by hoistStatic transform
|
||||||
test('with hoistStatic: true', () => {
|
test('with hoistStatic: true', () => {
|
||||||
const root = transformWithOnce(`<div><div v-once /></div>`, {
|
const root = transformWithOnce(`<div><div v-once /></div>`, {
|
||||||
hoistStatic: true
|
hoistStatic: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
expect(root.helpers).toContain(SET_BLOCK_TRACKING)
|
expect(root.helpers).toContain(SET_BLOCK_TRACKING)
|
||||||
|
@ -100,8 +100,8 @@ describe('compiler: v-once transform', () => {
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`
|
tag: `"div"`,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -119,14 +119,14 @@ describe('compiler: v-once transform', () => {
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
consequent: {
|
consequent: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"div"`
|
tag: `"div"`,
|
||||||
},
|
},
|
||||||
alternate: {
|
alternate: {
|
||||||
type: NodeTypes.VNODE_CALL,
|
type: NodeTypes.VNODE_CALL,
|
||||||
tag: `"p"`
|
tag: `"p"`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -138,8 +138,8 @@ describe('compiler: v-once transform', () => {
|
||||||
type: NodeTypes.FOR,
|
type: NodeTypes.FOR,
|
||||||
// should cache the entire v-for expression, not just a single branch
|
// should cache the entire v-for expression, not just a single branch
|
||||||
codegenNode: {
|
codegenNode: {
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import {
|
import {
|
||||||
CompilerOptions,
|
type CompilerOptions,
|
||||||
|
type ComponentNode,
|
||||||
|
type ElementNode,
|
||||||
|
ErrorCodes,
|
||||||
|
type ForNode,
|
||||||
|
NodeTypes,
|
||||||
|
type ObjectExpression,
|
||||||
|
type RenderSlotCall,
|
||||||
|
type SimpleExpressionNode,
|
||||||
|
type SlotsExpression,
|
||||||
|
type VNodeCall,
|
||||||
|
generate,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
generate,
|
|
||||||
ElementNode,
|
|
||||||
NodeTypes,
|
|
||||||
ErrorCodes,
|
|
||||||
ForNode,
|
|
||||||
ComponentNode,
|
|
||||||
VNodeCall,
|
|
||||||
SlotsExpression,
|
|
||||||
ObjectExpression,
|
|
||||||
SimpleExpressionNode,
|
|
||||||
RenderSlotCall
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import { transformElement } from '../../src/transforms/transformElement'
|
import { transformElement } from '../../src/transforms/transformElement'
|
||||||
import { transformOn } from '../../src/transforms/vOn'
|
import { transformOn } from '../../src/transforms/vOn'
|
||||||
|
@ -21,7 +21,7 @@ import { transformExpression } from '../../src/transforms/transformExpression'
|
||||||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||||
import {
|
import {
|
||||||
trackSlotScopes,
|
trackSlotScopes,
|
||||||
trackVForSlotScopes
|
trackVForSlotScopes,
|
||||||
} from '../../src/transforms/vSlot'
|
} from '../../src/transforms/vSlot'
|
||||||
import { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeHelpers'
|
import { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeHelpers'
|
||||||
import { createObjectMatcher, genFlagText } from '../testUtils'
|
import { createObjectMatcher, genFlagText } from '../testUtils'
|
||||||
|
@ -31,7 +31,7 @@ import { transformIf } from '../../src/transforms/vIf'
|
||||||
|
|
||||||
function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
||||||
const ast = parse(template, {
|
const ast = parse(template, {
|
||||||
whitespace: options.whitespace
|
whitespace: options.whitespace,
|
||||||
})
|
})
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [
|
nodeTransforms: [
|
||||||
|
@ -42,13 +42,13 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
||||||
: []),
|
: []),
|
||||||
transformSlotOutlet,
|
transformSlotOutlet,
|
||||||
transformElement,
|
transformElement,
|
||||||
trackSlotScopes
|
trackSlotScopes,
|
||||||
],
|
],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
on: transformOn,
|
on: transformOn,
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
root: ast,
|
root: ast,
|
||||||
|
@ -56,7 +56,7 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
||||||
ast.children[0].type === NodeTypes.ELEMENT
|
ast.children[0].type === NodeTypes.ELEMENT
|
||||||
? ((ast.children[0].codegenNode as VNodeCall)
|
? ((ast.children[0].codegenNode as VNodeCall)
|
||||||
.children as SlotsExpression)
|
.children as SlotsExpression)
|
||||||
: null
|
: null,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,25 +70,25 @@ function createSlotMatcher(obj: Record<string, any>, isDynamic = false) {
|
||||||
key: {
|
key: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
isStatic: !/^\[/.test(key),
|
isStatic: !/^\[/.test(key),
|
||||||
content: key.replace(/^\[|\]$/g, '')
|
content: key.replace(/^\[|\]$/g, ''),
|
||||||
},
|
},
|
||||||
value: obj[key]
|
value: obj[key],
|
||||||
} as any
|
} as any
|
||||||
})
|
})
|
||||||
.concat({
|
.concat({
|
||||||
key: { content: `_` },
|
key: { content: `_` },
|
||||||
value: {
|
value: {
|
||||||
content: isDynamic ? `2 /* DYNAMIC */` : `1 /* STABLE */`,
|
content: isDynamic ? `2 /* DYNAMIC */` : `1 /* STABLE */`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('compiler: transform component slots', () => {
|
describe('compiler: transform component slots', () => {
|
||||||
test('implicit default slot', () => {
|
test('implicit default slot', () => {
|
||||||
const { root, slots } = parseWithSlots(`<Comp><div/></Comp>`, {
|
const { root, slots } = parseWithSlots(`<Comp><div/></Comp>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher({
|
createSlotMatcher({
|
||||||
|
@ -98,11 +98,11 @@ describe('compiler: transform component slots', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: `div`
|
tag: `div`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -110,7 +110,7 @@ describe('compiler: transform component slots', () => {
|
||||||
test('on-component default slot', () => {
|
test('on-component default slot', () => {
|
||||||
const { root, slots } = parseWithSlots(
|
const { root, slots } = parseWithSlots(
|
||||||
`<Comp v-slot="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
`<Comp v-slot="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher({
|
createSlotMatcher({
|
||||||
|
@ -118,24 +118,24 @@ describe('compiler: transform component slots', () => {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `foo` }, ` }`]
|
children: [`{ `, { content: `foo` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`
|
content: `_ctx.bar`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -143,7 +143,7 @@ describe('compiler: transform component slots', () => {
|
||||||
test('on component named slot', () => {
|
test('on component named slot', () => {
|
||||||
const { root, slots } = parseWithSlots(
|
const { root, slots } = parseWithSlots(
|
||||||
`<Comp v-slot:named="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
`<Comp v-slot:named="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher({
|
createSlotMatcher({
|
||||||
|
@ -151,24 +151,24 @@ describe('compiler: transform component slots', () => {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `foo` }, ` }`]
|
children: [`{ `, { content: `foo` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`
|
content: `_ctx.bar`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -183,7 +183,7 @@ describe('compiler: transform component slots', () => {
|
||||||
{{ foo }}{{ bar }}
|
{{ foo }}{{ bar }}
|
||||||
</template>
|
</template>
|
||||||
</Comp>`,
|
</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher({
|
createSlotMatcher({
|
||||||
|
@ -191,45 +191,45 @@ describe('compiler: transform component slots', () => {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `foo` }, ` }`]
|
children: [`{ `, { content: `foo` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`
|
content: `_ctx.bar`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
two: {
|
two: {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `bar` }, ` }`]
|
children: [`{ `, { content: `bar` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.foo`
|
content: `_ctx.foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `bar`
|
content: `bar`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -237,7 +237,7 @@ describe('compiler: transform component slots', () => {
|
||||||
test('on component dynamically named slot', () => {
|
test('on component dynamically named slot', () => {
|
||||||
const { root, slots } = parseWithSlots(
|
const { root, slots } = parseWithSlots(
|
||||||
`<Comp v-slot:[named]="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
`<Comp v-slot:[named]="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher(
|
createSlotMatcher(
|
||||||
|
@ -246,26 +246,26 @@ describe('compiler: transform component slots', () => {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `foo` }, ` }`]
|
children: [`{ `, { content: `foo` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`
|
content: `_ctx.bar`,
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
true
|
},
|
||||||
)
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -274,7 +274,7 @@ describe('compiler: transform component slots', () => {
|
||||||
const { root, slots } = parseWithSlots(
|
const { root, slots } = parseWithSlots(
|
||||||
`<Comp>
|
`<Comp>
|
||||||
<template #one>foo</template>bar<span/>
|
<template #one>foo</template>bar<span/>
|
||||||
</Comp>`
|
</Comp>`,
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher({
|
createSlotMatcher({
|
||||||
|
@ -284,9 +284,9 @@ describe('compiler: transform component slots', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
default: {
|
default: {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
@ -294,15 +294,15 @@ describe('compiler: transform component slots', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `bar`
|
content: `bar`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: `span`
|
tag: `span`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -317,7 +317,7 @@ describe('compiler: transform component slots', () => {
|
||||||
{{ foo }}{{ bar }}
|
{{ foo }}{{ bar }}
|
||||||
</template>
|
</template>
|
||||||
</Comp>`,
|
</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher(
|
createSlotMatcher(
|
||||||
|
@ -326,47 +326,47 @@ describe('compiler: transform component slots', () => {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `foo` }, ` }`]
|
children: [`{ `, { content: `foo` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`
|
content: `_ctx.bar`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
'[_ctx.two]': {
|
'[_ctx.two]': {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `bar` }, ` }`]
|
children: [`{ `, { content: `bar` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.foo`
|
content: `_ctx.foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `bar`
|
content: `bar`,
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
true
|
},
|
||||||
)
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -381,7 +381,7 @@ describe('compiler: transform component slots', () => {
|
||||||
{{ foo }}{{ bar }}{{ baz }}
|
{{ foo }}{{ bar }}{{ baz }}
|
||||||
</template>
|
</template>
|
||||||
</Comp>`,
|
</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(
|
expect(slots).toMatchObject(
|
||||||
createSlotMatcher({
|
createSlotMatcher({
|
||||||
|
@ -389,7 +389,7 @@ describe('compiler: transform component slots', () => {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `foo` }, ` }`]
|
children: [`{ `, { content: `foo` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
|
@ -404,63 +404,63 @@ describe('compiler: transform component slots', () => {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: {
|
params: {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
children: [`{ `, { content: `bar` }, ` }`]
|
children: [`{ `, { content: `bar` }, ` }`],
|
||||||
},
|
},
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `bar`
|
content: `bar`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.baz`
|
content: `_ctx.baz`,
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
true
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
true,
|
||||||
),
|
),
|
||||||
// nested slot should be forced dynamic, since scope variables
|
// nested slot should be forced dynamic, since scope variables
|
||||||
// are not tracked as dependencies of the slot.
|
// are not tracked as dependencies of the slot.
|
||||||
patchFlag: genFlagText(PatchFlags.DYNAMIC_SLOTS)
|
patchFlag: genFlagText(PatchFlags.DYNAMIC_SLOTS),
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
// test scope
|
// test scope
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: ` `
|
content: ` `,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `foo`
|
content: `foo`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.bar`
|
content: `_ctx.bar`,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: {
|
content: {
|
||||||
content: `_ctx.baz`
|
content: `_ctx.baz`,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -469,13 +469,13 @@ describe('compiler: transform component slots', () => {
|
||||||
const { root } = parseWithSlots(
|
const { root } = parseWithSlots(
|
||||||
`<div v-for="i in list">
|
`<div v-for="i in list">
|
||||||
<Comp v-slot="bar">foo</Comp>
|
<Comp v-slot="bar">foo</Comp>
|
||||||
</div>`
|
</div>`,
|
||||||
)
|
)
|
||||||
const div = ((root.children[0] as ForNode).children[0] as ElementNode)
|
const div = ((root.children[0] as ForNode).children[0] as ElementNode)
|
||||||
.codegenNode as any
|
.codegenNode as any
|
||||||
const comp = div.children[0]
|
const comp = div.children[0]
|
||||||
expect(comp.codegenNode.patchFlag).toBe(
|
expect(comp.codegenNode.patchFlag).toBe(
|
||||||
genFlagText(PatchFlags.DYNAMIC_SLOTS)
|
genFlagText(PatchFlags.DYNAMIC_SLOTS),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -504,14 +504,14 @@ describe('compiler: transform component slots', () => {
|
||||||
`<div v-for="i in list">
|
`<div v-for="i in list">
|
||||||
<Comp v-slot="bar">foo</Comp>
|
<Comp v-slot="bar">foo</Comp>
|
||||||
</div>`,
|
</div>`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
|
|
||||||
assertDynamicSlots(
|
assertDynamicSlots(
|
||||||
`<div v-for="i in list">
|
`<div v-for="i in list">
|
||||||
<Comp v-slot="bar">{{ i }}</Comp>
|
<Comp v-slot="bar">{{ i }}</Comp>
|
||||||
</div>`,
|
</div>`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
|
|
||||||
// reference the component's own slot variable should not force dynamic slots
|
// reference the component's own slot variable should not force dynamic slots
|
||||||
|
@ -519,14 +519,14 @@ describe('compiler: transform component slots', () => {
|
||||||
`<Comp v-slot="foo">
|
`<Comp v-slot="foo">
|
||||||
<Comp v-slot="bar">{{ bar }}</Comp>
|
<Comp v-slot="bar">{{ bar }}</Comp>
|
||||||
</Comp>`,
|
</Comp>`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
|
|
||||||
assertDynamicSlots(
|
assertDynamicSlots(
|
||||||
`<Comp v-slot="foo">
|
`<Comp v-slot="foo">
|
||||||
<Comp v-slot="bar">{{ foo }}</Comp>
|
<Comp v-slot="bar">{{ foo }}</Comp>
|
||||||
</Comp>`,
|
</Comp>`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
|
|
||||||
// #2564
|
// #2564
|
||||||
|
@ -534,14 +534,14 @@ describe('compiler: transform component slots', () => {
|
||||||
`<div v-for="i in list">
|
`<div v-for="i in list">
|
||||||
<Comp v-slot="bar"><button @click="fn(i)" /></Comp>
|
<Comp v-slot="bar"><button @click="fn(i)" /></Comp>
|
||||||
</div>`,
|
</div>`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
|
|
||||||
assertDynamicSlots(
|
assertDynamicSlots(
|
||||||
`<div v-for="i in list">
|
`<div v-for="i in list">
|
||||||
<Comp v-slot="bar"><button @click="fn()" /></Comp>
|
<Comp v-slot="bar"><button @click="fn()" /></Comp>
|
||||||
</div>`,
|
</div>`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -549,14 +549,14 @@ describe('compiler: transform component slots', () => {
|
||||||
const { root, slots } = parseWithSlots(
|
const { root, slots } = parseWithSlots(
|
||||||
`<Comp>
|
`<Comp>
|
||||||
<template #one v-if="ok">hello</template>
|
<template #one v-if="ok">hello</template>
|
||||||
</Comp>`
|
</Comp>`,
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject({
|
expect(slots).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_SLOTS,
|
callee: CREATE_SLOTS,
|
||||||
arguments: [
|
arguments: [
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
_: `[2 /* DYNAMIC */]`
|
_: `[2 /* DYNAMIC */]`,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
|
@ -568,21 +568,21 @@ describe('compiler: transform component slots', () => {
|
||||||
name: `one`,
|
name: `one`,
|
||||||
fn: {
|
fn: {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
returns: [{ type: NodeTypes.TEXT, content: `hello` }]
|
returns: [{ type: NodeTypes.TEXT, content: `hello` }],
|
||||||
},
|
},
|
||||||
key: `0`
|
key: `0`,
|
||||||
}),
|
}),
|
||||||
alternate: {
|
alternate: {
|
||||||
content: `undefined`,
|
content: `undefined`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
||||||
PatchFlags.DYNAMIC_SLOTS + ''
|
PatchFlags.DYNAMIC_SLOTS + '',
|
||||||
)
|
)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -592,14 +592,14 @@ describe('compiler: transform component slots', () => {
|
||||||
`<Comp>
|
`<Comp>
|
||||||
<template #one="props" v-if="ok">{{ props }}</template>
|
<template #one="props" v-if="ok">{{ props }}</template>
|
||||||
</Comp>`,
|
</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject({
|
expect(slots).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_SLOTS,
|
callee: CREATE_SLOTS,
|
||||||
arguments: [
|
arguments: [
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
_: `[2 /* DYNAMIC */]`
|
_: `[2 /* DYNAMIC */]`,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
|
@ -615,23 +615,23 @@ describe('compiler: transform component slots', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: { content: `props` }
|
content: { content: `props` },
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
key: `0`
|
],
|
||||||
|
},
|
||||||
|
key: `0`,
|
||||||
}),
|
}),
|
||||||
alternate: {
|
alternate: {
|
||||||
content: `undefined`,
|
content: `undefined`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
||||||
PatchFlags.DYNAMIC_SLOTS + ''
|
PatchFlags.DYNAMIC_SLOTS + '',
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -642,14 +642,14 @@ describe('compiler: transform component slots', () => {
|
||||||
<template #one v-if="ok">foo</template>
|
<template #one v-if="ok">foo</template>
|
||||||
<template #two="props" v-else-if="orNot">bar</template>
|
<template #two="props" v-else-if="orNot">bar</template>
|
||||||
<template #one v-else>baz</template>
|
<template #one v-else>baz</template>
|
||||||
</Comp>`
|
</Comp>`,
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject({
|
expect(slots).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_SLOTS,
|
callee: CREATE_SLOTS,
|
||||||
arguments: [
|
arguments: [
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
_: `[2 /* DYNAMIC */]`
|
_: `[2 /* DYNAMIC */]`,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
|
@ -662,9 +662,9 @@ describe('compiler: transform component slots', () => {
|
||||||
fn: {
|
fn: {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: undefined,
|
params: undefined,
|
||||||
returns: [{ type: NodeTypes.TEXT, content: `foo` }]
|
returns: [{ type: NodeTypes.TEXT, content: `foo` }],
|
||||||
},
|
},
|
||||||
key: `0`
|
key: `0`,
|
||||||
}),
|
}),
|
||||||
alternate: {
|
alternate: {
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
|
@ -674,27 +674,27 @@ describe('compiler: transform component slots', () => {
|
||||||
fn: {
|
fn: {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: { content: `props` },
|
params: { content: `props` },
|
||||||
returns: [{ type: NodeTypes.TEXT, content: `bar` }]
|
returns: [{ type: NodeTypes.TEXT, content: `bar` }],
|
||||||
},
|
},
|
||||||
key: `1`
|
key: `1`,
|
||||||
}),
|
}),
|
||||||
alternate: createObjectMatcher({
|
alternate: createObjectMatcher({
|
||||||
name: `one`,
|
name: `one`,
|
||||||
fn: {
|
fn: {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
params: undefined,
|
params: undefined,
|
||||||
returns: [{ type: NodeTypes.TEXT, content: `baz` }]
|
returns: [{ type: NodeTypes.TEXT, content: `baz` }],
|
||||||
},
|
},
|
||||||
key: `2`
|
key: `2`,
|
||||||
})
|
}),
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
||||||
PatchFlags.DYNAMIC_SLOTS + ''
|
PatchFlags.DYNAMIC_SLOTS + '',
|
||||||
)
|
)
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -704,14 +704,14 @@ describe('compiler: transform component slots', () => {
|
||||||
`<Comp>
|
`<Comp>
|
||||||
<template v-for="name in list" #[name]>{{ name }}</template>
|
<template v-for="name in list" #[name]>{{ name }}</template>
|
||||||
</Comp>`,
|
</Comp>`,
|
||||||
{ prefixIdentifiers: true }
|
{ prefixIdentifiers: true },
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject({
|
expect(slots).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: CREATE_SLOTS,
|
callee: CREATE_SLOTS,
|
||||||
arguments: [
|
arguments: [
|
||||||
createObjectMatcher({
|
createObjectMatcher({
|
||||||
_: `[2 /* DYNAMIC */]`
|
_: `[2 /* DYNAMIC */]`,
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
|
@ -731,20 +731,20 @@ describe('compiler: transform component slots', () => {
|
||||||
returns: [
|
returns: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: { content: `name`, isStatic: false }
|
content: { content: `name`, isStatic: false },
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
})
|
}),
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
||||||
PatchFlags.DYNAMIC_SLOTS + ''
|
PatchFlags.DYNAMIC_SLOTS + '',
|
||||||
)
|
)
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -755,13 +755,13 @@ describe('compiler: transform component slots', () => {
|
||||||
properties: [
|
properties: [
|
||||||
{
|
{
|
||||||
key: { content: `default` },
|
key: { content: `default` },
|
||||||
value: { type: NodeTypes.JS_FUNCTION_EXPRESSION }
|
value: { type: NodeTypes.JS_FUNCTION_EXPRESSION },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: { content: `_` },
|
key: { content: `_` },
|
||||||
value: { content: `3 /* FORWARDED */` }
|
value: { content: `3 /* FORWARDED */` },
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
test('<slot> tag only', () => {
|
test('<slot> tag only', () => {
|
||||||
const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)
|
const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)
|
||||||
|
@ -780,7 +780,7 @@ describe('compiler: transform component slots', () => {
|
||||||
|
|
||||||
test('<slot> tag w/ template', () => {
|
test('<slot> tag w/ template', () => {
|
||||||
const { slots } = parseWithSlots(
|
const { slots } = parseWithSlots(
|
||||||
`<Comp><template #default><slot/></template></Comp>`
|
`<Comp><template #default><slot/></template></Comp>`,
|
||||||
)
|
)
|
||||||
expect(slots).toMatchObject(toMatch)
|
expect(slots).toMatchObject(toMatch)
|
||||||
})
|
})
|
||||||
|
@ -793,7 +793,7 @@ describe('compiler: transform component slots', () => {
|
||||||
// # fix: #6900
|
// # fix: #6900
|
||||||
test('consistent behavior of @xxx:modelValue and @xxx:model-value', () => {
|
test('consistent behavior of @xxx:modelValue and @xxx:model-value', () => {
|
||||||
const { root: rootUpper } = parseWithSlots(
|
const { root: rootUpper } = parseWithSlots(
|
||||||
`<div><slot @foo:modelValue="handler" /></div>`
|
`<div><slot @foo:modelValue="handler" /></div>`,
|
||||||
)
|
)
|
||||||
const slotNodeUpper = (rootUpper.codegenNode! as VNodeCall)
|
const slotNodeUpper = (rootUpper.codegenNode! as VNodeCall)
|
||||||
.children as ElementNode[]
|
.children as ElementNode[]
|
||||||
|
@ -805,19 +805,19 @@ describe('compiler: transform component slots', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'onFoo:modelValue'
|
content: 'onFoo:modelValue',
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `handler`,
|
content: `handler`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
|
|
||||||
const { root } = parseWithSlots(
|
const { root } = parseWithSlots(
|
||||||
`<div><slot @foo:model-Value="handler" /></div>`
|
`<div><slot @foo:model-Value="handler" /></div>`,
|
||||||
)
|
)
|
||||||
const slotNode = (root.codegenNode! as VNodeCall)
|
const slotNode = (root.codegenNode! as VNodeCall)
|
||||||
.children as ElementNode[]
|
.children as ElementNode[]
|
||||||
|
@ -828,15 +828,15 @@ describe('compiler: transform component slots', () => {
|
||||||
{
|
{
|
||||||
key: {
|
key: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: 'onFoo:modelValue'
|
content: 'onFoo:modelValue',
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `handler`,
|
content: `handler`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -853,14 +853,14 @@ describe('compiler: transform component slots', () => {
|
||||||
start: {
|
start: {
|
||||||
offset: index,
|
offset: index,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 1
|
column: index + 1,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
offset: index + 3,
|
offset: index + 3,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 4
|
column: index + 4,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -875,14 +875,14 @@ describe('compiler: transform component slots', () => {
|
||||||
start: {
|
start: {
|
||||||
offset: index,
|
offset: index,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 1
|
column: index + 1,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
offset: index + 4,
|
offset: index + 4,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 5
|
column: index + 5,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -897,14 +897,14 @@ describe('compiler: transform component slots', () => {
|
||||||
start: {
|
start: {
|
||||||
offset: index,
|
offset: index,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 1
|
column: index + 1,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
offset: index + 4,
|
offset: index + 4,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 5
|
column: index + 5,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -919,14 +919,14 @@ describe('compiler: transform component slots', () => {
|
||||||
start: {
|
start: {
|
||||||
offset: index,
|
offset: index,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 1
|
column: index + 1,
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
offset: index + 6,
|
offset: index + 6,
|
||||||
line: 1,
|
line: 1,
|
||||||
column: index + 7
|
column: index + 7,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -940,11 +940,11 @@ describe('compiler: transform component slots', () => {
|
||||||
</Comp>
|
</Comp>
|
||||||
`
|
`
|
||||||
const { root } = parseWithSlots(source, {
|
const { root } = parseWithSlots(source, {
|
||||||
whitespace: 'preserve'
|
whitespace: 'preserve',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
`Extraneous children found when component already has explicitly named default slot.`
|
`Extraneous children found when component already has explicitly named default slot.`,
|
||||||
).not.toHaveBeenWarned()
|
).not.toHaveBeenWarned()
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -957,11 +957,11 @@ describe('compiler: transform component slots', () => {
|
||||||
</Comp>
|
</Comp>
|
||||||
`
|
`
|
||||||
const { root } = parseWithSlots(source, {
|
const { root } = parseWithSlots(source, {
|
||||||
whitespace: 'preserve'
|
whitespace: 'preserve',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
`Extraneous children found when component already has explicitly named default slot.`
|
`Extraneous children found when component already has explicitly named default slot.`,
|
||||||
).not.toHaveBeenWarned()
|
).not.toHaveBeenWarned()
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -974,7 +974,7 @@ describe('compiler: transform component slots', () => {
|
||||||
</Comp>
|
</Comp>
|
||||||
`
|
`
|
||||||
const { root } = parseWithSlots(source, {
|
const { root } = parseWithSlots(source, {
|
||||||
whitespace: 'preserve'
|
whitespace: 'preserve',
|
||||||
})
|
})
|
||||||
|
|
||||||
// slots is vnodeCall's children as an ObjectExpression
|
// slots is vnodeCall's children as an ObjectExpression
|
||||||
|
@ -984,7 +984,7 @@ describe('compiler: transform component slots', () => {
|
||||||
// should be: header, footer, _ (no default)
|
// should be: header, footer, _ (no default)
|
||||||
expect(slots.length).toBe(3)
|
expect(slots.length).toBe(3)
|
||||||
expect(
|
expect(
|
||||||
slots.some(p => (p.key as SimpleExpressionNode).content === 'default')
|
slots.some(p => (p.key as SimpleExpressionNode).content === 'default'),
|
||||||
).toBe(false)
|
).toBe(false)
|
||||||
|
|
||||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { TransformContext } from '../src'
|
import type { TransformContext } from '../src'
|
||||||
import { Position } from '../src/ast'
|
import type { Position } from '../src/ast'
|
||||||
import {
|
import {
|
||||||
advancePositionWithClone,
|
advancePositionWithClone,
|
||||||
isMemberExpressionNode,
|
|
||||||
isMemberExpressionBrowser,
|
isMemberExpressionBrowser,
|
||||||
toValidAssetId
|
isMemberExpressionNode,
|
||||||
|
toValidAssetId,
|
||||||
} from '../src/utils'
|
} from '../src/utils'
|
||||||
|
|
||||||
function p(line: number, column: number, offset: number): Position {
|
function p(line: number, column: number, offset: number): Position {
|
||||||
|
@ -108,6 +108,6 @@ test('toValidAssetId', () => {
|
||||||
expect(toValidAssetId('div', 'filter')).toBe('_filter_div')
|
expect(toValidAssetId('div', 'filter')).toBe('_filter_div')
|
||||||
expect(toValidAssetId('foo-bar', 'component')).toBe('_component_foo_bar')
|
expect(toValidAssetId('foo-bar', 'component')).toBe('_component_foo_bar')
|
||||||
expect(toValidAssetId('test-测试-1', 'component')).toBe(
|
expect(toValidAssetId('test-测试-1', 'component')).toBe(
|
||||||
'_component_test_2797935797_1'
|
'_component_test_2797935797_1',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import { isString } from '@vue/shared'
|
import { isString } from '@vue/shared'
|
||||||
import {
|
import {
|
||||||
RENDER_SLOT,
|
|
||||||
CREATE_SLOTS,
|
|
||||||
RENDER_LIST,
|
|
||||||
OPEN_BLOCK,
|
|
||||||
FRAGMENT,
|
|
||||||
WITH_DIRECTIVES,
|
|
||||||
WITH_MEMO,
|
|
||||||
CREATE_VNODE,
|
|
||||||
CREATE_ELEMENT_VNODE,
|
|
||||||
CREATE_BLOCK,
|
CREATE_BLOCK,
|
||||||
CREATE_ELEMENT_BLOCK
|
CREATE_ELEMENT_BLOCK,
|
||||||
|
CREATE_ELEMENT_VNODE,
|
||||||
|
type CREATE_SLOTS,
|
||||||
|
CREATE_VNODE,
|
||||||
|
type FRAGMENT,
|
||||||
|
OPEN_BLOCK,
|
||||||
|
type RENDER_LIST,
|
||||||
|
type RENDER_SLOT,
|
||||||
|
WITH_DIRECTIVES,
|
||||||
|
type WITH_MEMO,
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { PropsExpression } from './transforms/transformElement'
|
import type { PropsExpression } from './transforms/transformElement'
|
||||||
import { ImportItem, TransformContext } from './transform'
|
import type { ImportItem, TransformContext } from './transform'
|
||||||
import { Node as BabelNode } from '@babel/types'
|
import type { Node as BabelNode } from '@babel/types'
|
||||||
|
|
||||||
// Vue template is a platform-agnostic superset of HTML (syntax only).
|
// Vue template is a platform-agnostic superset of HTML (syntax only).
|
||||||
// More namespaces can be declared by platform specific compilers.
|
// More namespaces can be declared by platform specific compilers.
|
||||||
|
@ -23,7 +23,7 @@ export type Namespace = number
|
||||||
export enum Namespaces {
|
export enum Namespaces {
|
||||||
HTML,
|
HTML,
|
||||||
SVG,
|
SVG,
|
||||||
MATH_ML
|
MATH_ML,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum NodeTypes {
|
export enum NodeTypes {
|
||||||
|
@ -57,14 +57,14 @@ export enum NodeTypes {
|
||||||
JS_IF_STATEMENT,
|
JS_IF_STATEMENT,
|
||||||
JS_ASSIGNMENT_EXPRESSION,
|
JS_ASSIGNMENT_EXPRESSION,
|
||||||
JS_SEQUENCE_EXPRESSION,
|
JS_SEQUENCE_EXPRESSION,
|
||||||
JS_RETURN_STATEMENT
|
JS_RETURN_STATEMENT,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ElementTypes {
|
export enum ElementTypes {
|
||||||
ELEMENT,
|
ELEMENT,
|
||||||
COMPONENT,
|
COMPONENT,
|
||||||
SLOT,
|
SLOT,
|
||||||
TEMPLATE
|
TEMPLATE,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Node {
|
export interface Node {
|
||||||
|
@ -219,7 +219,7 @@ export enum ConstantTypes {
|
||||||
NOT_CONSTANT = 0,
|
NOT_CONSTANT = 0,
|
||||||
CAN_SKIP_PATCH,
|
CAN_SKIP_PATCH,
|
||||||
CAN_HOIST,
|
CAN_HOIST,
|
||||||
CAN_STRINGIFY
|
CAN_STRINGIFY,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SimpleExpressionNode extends Node {
|
export interface SimpleExpressionNode extends Node {
|
||||||
|
@ -495,7 +495,7 @@ export interface RenderSlotCall extends CallExpression {
|
||||||
string,
|
string,
|
||||||
string | ExpressionNode,
|
string | ExpressionNode,
|
||||||
PropsExpression | '{}',
|
PropsExpression | '{}',
|
||||||
TemplateChildNode[]
|
TemplateChildNode[],
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -582,12 +582,12 @@ export interface ForIteratorExpression extends FunctionExpression {
|
||||||
export const locStub: SourceLocation = {
|
export const locStub: SourceLocation = {
|
||||||
start: { line: 1, column: 1, offset: 0 },
|
start: { line: 1, column: 1, offset: 0 },
|
||||||
end: { line: 1, column: 1, offset: 0 },
|
end: { line: 1, column: 1, offset: 0 },
|
||||||
source: ''
|
source: '',
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createRoot(
|
export function createRoot(
|
||||||
children: TemplateChildNode[],
|
children: TemplateChildNode[],
|
||||||
source = ''
|
source = '',
|
||||||
): RootNode {
|
): RootNode {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.ROOT,
|
type: NodeTypes.ROOT,
|
||||||
|
@ -601,7 +601,7 @@ export function createRoot(
|
||||||
cached: 0,
|
cached: 0,
|
||||||
temps: 0,
|
temps: 0,
|
||||||
codegenNode: undefined,
|
codegenNode: undefined,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -616,7 +616,7 @@ export function createVNodeCall(
|
||||||
isBlock: VNodeCall['isBlock'] = false,
|
isBlock: VNodeCall['isBlock'] = false,
|
||||||
disableTracking: VNodeCall['disableTracking'] = false,
|
disableTracking: VNodeCall['disableTracking'] = false,
|
||||||
isComponent: VNodeCall['isComponent'] = false,
|
isComponent: VNodeCall['isComponent'] = false,
|
||||||
loc = locStub
|
loc = locStub,
|
||||||
): VNodeCall {
|
): VNodeCall {
|
||||||
if (context) {
|
if (context) {
|
||||||
if (isBlock) {
|
if (isBlock) {
|
||||||
|
@ -641,41 +641,41 @@ export function createVNodeCall(
|
||||||
isBlock,
|
isBlock,
|
||||||
disableTracking,
|
disableTracking,
|
||||||
isComponent,
|
isComponent,
|
||||||
loc
|
loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createArrayExpression(
|
export function createArrayExpression(
|
||||||
elements: ArrayExpression['elements'],
|
elements: ArrayExpression['elements'],
|
||||||
loc: SourceLocation = locStub
|
loc: SourceLocation = locStub,
|
||||||
): ArrayExpression {
|
): ArrayExpression {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
loc,
|
loc,
|
||||||
elements
|
elements,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createObjectExpression(
|
export function createObjectExpression(
|
||||||
properties: ObjectExpression['properties'],
|
properties: ObjectExpression['properties'],
|
||||||
loc: SourceLocation = locStub
|
loc: SourceLocation = locStub,
|
||||||
): ObjectExpression {
|
): ObjectExpression {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||||
loc,
|
loc,
|
||||||
properties
|
properties,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createObjectProperty(
|
export function createObjectProperty(
|
||||||
key: Property['key'] | string,
|
key: Property['key'] | string,
|
||||||
value: Property['value']
|
value: Property['value'],
|
||||||
): Property {
|
): Property {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
loc: locStub,
|
loc: locStub,
|
||||||
key: isString(key) ? createSimpleExpression(key, true) : key,
|
key: isString(key) ? createSimpleExpression(key, true) : key,
|
||||||
value
|
value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,38 +683,38 @@ export function createSimpleExpression(
|
||||||
content: SimpleExpressionNode['content'],
|
content: SimpleExpressionNode['content'],
|
||||||
isStatic: SimpleExpressionNode['isStatic'] = false,
|
isStatic: SimpleExpressionNode['isStatic'] = false,
|
||||||
loc: SourceLocation = locStub,
|
loc: SourceLocation = locStub,
|
||||||
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT
|
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT,
|
||||||
): SimpleExpressionNode {
|
): SimpleExpressionNode {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
loc,
|
loc,
|
||||||
content,
|
content,
|
||||||
isStatic,
|
isStatic,
|
||||||
constType: isStatic ? ConstantTypes.CAN_STRINGIFY : constType
|
constType: isStatic ? ConstantTypes.CAN_STRINGIFY : constType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createInterpolation(
|
export function createInterpolation(
|
||||||
content: InterpolationNode['content'] | string,
|
content: InterpolationNode['content'] | string,
|
||||||
loc: SourceLocation
|
loc: SourceLocation,
|
||||||
): InterpolationNode {
|
): InterpolationNode {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
loc,
|
loc,
|
||||||
content: isString(content)
|
content: isString(content)
|
||||||
? createSimpleExpression(content, false, loc)
|
? createSimpleExpression(content, false, loc)
|
||||||
: content
|
: content,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCompoundExpression(
|
export function createCompoundExpression(
|
||||||
children: CompoundExpressionNode['children'],
|
children: CompoundExpressionNode['children'],
|
||||||
loc: SourceLocation = locStub
|
loc: SourceLocation = locStub,
|
||||||
): CompoundExpressionNode {
|
): CompoundExpressionNode {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||||
loc,
|
loc,
|
||||||
children
|
children,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,13 +725,13 @@ type InferCodegenNodeType<T> = T extends typeof RENDER_SLOT
|
||||||
export function createCallExpression<T extends CallExpression['callee']>(
|
export function createCallExpression<T extends CallExpression['callee']>(
|
||||||
callee: T,
|
callee: T,
|
||||||
args: CallExpression['arguments'] = [],
|
args: CallExpression['arguments'] = [],
|
||||||
loc: SourceLocation = locStub
|
loc: SourceLocation = locStub,
|
||||||
): InferCodegenNodeType<T> {
|
): InferCodegenNodeType<T> {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
loc,
|
loc,
|
||||||
callee,
|
callee,
|
||||||
arguments: args
|
arguments: args,
|
||||||
} as InferCodegenNodeType<T>
|
} as InferCodegenNodeType<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -740,7 +740,7 @@ export function createFunctionExpression(
|
||||||
returns: FunctionExpression['returns'] = undefined,
|
returns: FunctionExpression['returns'] = undefined,
|
||||||
newline: boolean = false,
|
newline: boolean = false,
|
||||||
isSlot: boolean = false,
|
isSlot: boolean = false,
|
||||||
loc: SourceLocation = locStub
|
loc: SourceLocation = locStub,
|
||||||
): FunctionExpression {
|
): FunctionExpression {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||||
|
@ -748,7 +748,7 @@ export function createFunctionExpression(
|
||||||
returns,
|
returns,
|
||||||
newline,
|
newline,
|
||||||
isSlot,
|
isSlot,
|
||||||
loc
|
loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +756,7 @@ export function createConditionalExpression(
|
||||||
test: ConditionalExpression['test'],
|
test: ConditionalExpression['test'],
|
||||||
consequent: ConditionalExpression['consequent'],
|
consequent: ConditionalExpression['consequent'],
|
||||||
alternate: ConditionalExpression['alternate'],
|
alternate: ConditionalExpression['alternate'],
|
||||||
newline = true
|
newline = true,
|
||||||
): ConditionalExpression {
|
): ConditionalExpression {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||||
|
@ -764,87 +764,87 @@ export function createConditionalExpression(
|
||||||
consequent,
|
consequent,
|
||||||
alternate,
|
alternate,
|
||||||
newline,
|
newline,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createCacheExpression(
|
export function createCacheExpression(
|
||||||
index: number,
|
index: number,
|
||||||
value: JSChildNode,
|
value: JSChildNode,
|
||||||
isVNode: boolean = false
|
isVNode: boolean = false,
|
||||||
): CacheExpression {
|
): CacheExpression {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index,
|
index,
|
||||||
value,
|
value,
|
||||||
isVNode,
|
isVNode,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createBlockStatement(
|
export function createBlockStatement(
|
||||||
body: BlockStatement['body']
|
body: BlockStatement['body'],
|
||||||
): BlockStatement {
|
): BlockStatement {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_BLOCK_STATEMENT,
|
type: NodeTypes.JS_BLOCK_STATEMENT,
|
||||||
body,
|
body,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTemplateLiteral(
|
export function createTemplateLiteral(
|
||||||
elements: TemplateLiteral['elements']
|
elements: TemplateLiteral['elements'],
|
||||||
): TemplateLiteral {
|
): TemplateLiteral {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_TEMPLATE_LITERAL,
|
type: NodeTypes.JS_TEMPLATE_LITERAL,
|
||||||
elements,
|
elements,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createIfStatement(
|
export function createIfStatement(
|
||||||
test: IfStatement['test'],
|
test: IfStatement['test'],
|
||||||
consequent: IfStatement['consequent'],
|
consequent: IfStatement['consequent'],
|
||||||
alternate?: IfStatement['alternate']
|
alternate?: IfStatement['alternate'],
|
||||||
): IfStatement {
|
): IfStatement {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_IF_STATEMENT,
|
type: NodeTypes.JS_IF_STATEMENT,
|
||||||
test,
|
test,
|
||||||
consequent,
|
consequent,
|
||||||
alternate,
|
alternate,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createAssignmentExpression(
|
export function createAssignmentExpression(
|
||||||
left: AssignmentExpression['left'],
|
left: AssignmentExpression['left'],
|
||||||
right: AssignmentExpression['right']
|
right: AssignmentExpression['right'],
|
||||||
): AssignmentExpression {
|
): AssignmentExpression {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_ASSIGNMENT_EXPRESSION,
|
type: NodeTypes.JS_ASSIGNMENT_EXPRESSION,
|
||||||
left,
|
left,
|
||||||
right,
|
right,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createSequenceExpression(
|
export function createSequenceExpression(
|
||||||
expressions: SequenceExpression['expressions']
|
expressions: SequenceExpression['expressions'],
|
||||||
): SequenceExpression {
|
): SequenceExpression {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
||||||
expressions,
|
expressions,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createReturnStatement(
|
export function createReturnStatement(
|
||||||
returns: ReturnStatement['returns']
|
returns: ReturnStatement['returns'],
|
||||||
): ReturnStatement {
|
): ReturnStatement {
|
||||||
return {
|
return {
|
||||||
type: NodeTypes.JS_RETURN_STATEMENT,
|
type: NodeTypes.JS_RETURN_STATEMENT,
|
||||||
returns,
|
returns,
|
||||||
loc: locStub
|
loc: locStub,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,7 +858,7 @@ export function getVNodeBlockHelper(ssr: boolean, isComponent: boolean) {
|
||||||
|
|
||||||
export function convertToBlock(
|
export function convertToBlock(
|
||||||
node: VNodeCall,
|
node: VNodeCall,
|
||||||
{ helper, removeHelper, inSSR }: TransformContext
|
{ helper, removeHelper, inSSR }: TransformContext,
|
||||||
) {
|
) {
|
||||||
if (!node.isBlock) {
|
if (!node.isBlock) {
|
||||||
node.isBlock = true
|
node.isBlock = true
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
// should only use types from @babel/types
|
// should only use types from @babel/types
|
||||||
// do not import runtime methods
|
// do not import runtime methods
|
||||||
import type {
|
import type {
|
||||||
|
BlockStatement,
|
||||||
|
Function,
|
||||||
Identifier,
|
Identifier,
|
||||||
Node,
|
Node,
|
||||||
Function,
|
|
||||||
ObjectProperty,
|
ObjectProperty,
|
||||||
BlockStatement,
|
Program,
|
||||||
Program
|
|
||||||
} from '@babel/types'
|
} from '@babel/types'
|
||||||
import { walk } from 'estree-walker'
|
import { walk } from 'estree-walker'
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@ export function walkIdentifiers(
|
||||||
parent: Node,
|
parent: Node,
|
||||||
parentStack: Node[],
|
parentStack: Node[],
|
||||||
isReference: boolean,
|
isReference: boolean,
|
||||||
isLocal: boolean
|
isLocal: boolean,
|
||||||
) => void,
|
) => void,
|
||||||
includeAll = false,
|
includeAll = false,
|
||||||
parentStack: Node[] = [],
|
parentStack: Node[] = [],
|
||||||
knownIds: Record<string, number> = Object.create(null)
|
knownIds: Record<string, number> = Object.create(null),
|
||||||
) {
|
) {
|
||||||
if (__BROWSER__) {
|
if (__BROWSER__) {
|
||||||
return
|
return
|
||||||
|
@ -61,7 +61,7 @@ export function walkIdentifiers(
|
||||||
// walk function expressions and add its arguments to known identifiers
|
// walk function expressions and add its arguments to known identifiers
|
||||||
// so that we don't prefix them
|
// so that we don't prefix them
|
||||||
walkFunctionParams(node, id =>
|
walkFunctionParams(node, id =>
|
||||||
markScopeIdentifier(node, id, knownIds)
|
markScopeIdentifier(node, id, knownIds),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (node.type === 'BlockStatement') {
|
} else if (node.type === 'BlockStatement') {
|
||||||
|
@ -70,7 +70,7 @@ export function walkIdentifiers(
|
||||||
} else {
|
} else {
|
||||||
// #3445 record block-level local variables
|
// #3445 record block-level local variables
|
||||||
walkBlockDeclarations(node, id =>
|
walkBlockDeclarations(node, id =>
|
||||||
markScopeIdentifier(node, id, knownIds)
|
markScopeIdentifier(node, id, knownIds),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,14 +85,14 @@ export function walkIdentifiers(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isReferencedIdentifier(
|
export function isReferencedIdentifier(
|
||||||
id: Identifier,
|
id: Identifier,
|
||||||
parent: Node | null,
|
parent: Node | null,
|
||||||
parentStack: Node[]
|
parentStack: Node[],
|
||||||
) {
|
) {
|
||||||
if (__BROWSER__) {
|
if (__BROWSER__) {
|
||||||
return false
|
return false
|
||||||
|
@ -127,7 +127,7 @@ export function isReferencedIdentifier(
|
||||||
|
|
||||||
export function isInDestructureAssignment(
|
export function isInDestructureAssignment(
|
||||||
parent: Node,
|
parent: Node,
|
||||||
parentStack: Node[]
|
parentStack: Node[],
|
||||||
): boolean {
|
): boolean {
|
||||||
if (
|
if (
|
||||||
parent &&
|
parent &&
|
||||||
|
@ -148,7 +148,7 @@ export function isInDestructureAssignment(
|
||||||
|
|
||||||
export function walkFunctionParams(
|
export function walkFunctionParams(
|
||||||
node: Function,
|
node: Function,
|
||||||
onIdent: (id: Identifier) => void
|
onIdent: (id: Identifier) => void,
|
||||||
) {
|
) {
|
||||||
for (const p of node.params) {
|
for (const p of node.params) {
|
||||||
for (const id of extractIdentifiers(p)) {
|
for (const id of extractIdentifiers(p)) {
|
||||||
|
@ -159,7 +159,7 @@ export function walkFunctionParams(
|
||||||
|
|
||||||
export function walkBlockDeclarations(
|
export function walkBlockDeclarations(
|
||||||
block: BlockStatement | Program,
|
block: BlockStatement | Program,
|
||||||
onIdent: (node: Identifier) => void
|
onIdent: (node: Identifier) => void,
|
||||||
) {
|
) {
|
||||||
for (const stmt of block.body) {
|
for (const stmt of block.body) {
|
||||||
if (stmt.type === 'VariableDeclaration') {
|
if (stmt.type === 'VariableDeclaration') {
|
||||||
|
@ -194,7 +194,7 @@ export function walkBlockDeclarations(
|
||||||
|
|
||||||
export function extractIdentifiers(
|
export function extractIdentifiers(
|
||||||
param: Node,
|
param: Node,
|
||||||
nodes: Identifier[] = []
|
nodes: Identifier[] = [],
|
||||||
): Identifier[] {
|
): Identifier[] {
|
||||||
switch (param.type) {
|
switch (param.type) {
|
||||||
case 'Identifier':
|
case 'Identifier':
|
||||||
|
@ -248,7 +248,7 @@ function markKnownIds(name: string, knownIds: Record<string, number>) {
|
||||||
function markScopeIdentifier(
|
function markScopeIdentifier(
|
||||||
node: Node & { scopeIds?: Set<string> },
|
node: Node & { scopeIds?: Set<string> },
|
||||||
child: Identifier,
|
child: Identifier,
|
||||||
knownIds: Record<string, number>
|
knownIds: Record<string, number>,
|
||||||
) {
|
) {
|
||||||
const { name } = child
|
const { name } = child
|
||||||
if (node.scopeIds && node.scopeIds.has(name)) {
|
if (node.scopeIds && node.scopeIds.has(name)) {
|
||||||
|
@ -453,7 +453,7 @@ export const TS_NODE_TYPES = [
|
||||||
'TSTypeAssertion', // (<number>foo)
|
'TSTypeAssertion', // (<number>foo)
|
||||||
'TSNonNullExpression', // foo!
|
'TSNonNullExpression', // foo!
|
||||||
'TSInstantiationExpression', // foo<string>
|
'TSInstantiationExpression', // foo<string>
|
||||||
'TSSatisfiesExpression' // foo satisfies T
|
'TSSatisfiesExpression', // foo satisfies T
|
||||||
]
|
]
|
||||||
|
|
||||||
export function unwrapTSNode(node: Node): Node {
|
export function unwrapTSNode(node: Node): Node {
|
||||||
|
|
|
@ -1,60 +1,60 @@
|
||||||
import { CodegenOptions } from './options'
|
import type { CodegenOptions } from './options'
|
||||||
import {
|
import {
|
||||||
RootNode,
|
type ArrayExpression,
|
||||||
TemplateChildNode,
|
type AssignmentExpression,
|
||||||
TextNode,
|
type CacheExpression,
|
||||||
CommentNode,
|
type CallExpression,
|
||||||
ExpressionNode,
|
type CommentNode,
|
||||||
|
type CompoundExpressionNode,
|
||||||
|
type ConditionalExpression,
|
||||||
|
type ExpressionNode,
|
||||||
|
type FunctionExpression,
|
||||||
|
type IfStatement,
|
||||||
|
type InterpolationNode,
|
||||||
|
type JSChildNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
JSChildNode,
|
type ObjectExpression,
|
||||||
CallExpression,
|
type Position,
|
||||||
ArrayExpression,
|
type ReturnStatement,
|
||||||
ObjectExpression,
|
type RootNode,
|
||||||
Position,
|
type SSRCodegenNode,
|
||||||
InterpolationNode,
|
type SequenceExpression,
|
||||||
CompoundExpressionNode,
|
type SimpleExpressionNode,
|
||||||
SimpleExpressionNode,
|
type TemplateChildNode,
|
||||||
FunctionExpression,
|
type TemplateLiteral,
|
||||||
ConditionalExpression,
|
type TextNode,
|
||||||
CacheExpression,
|
type VNodeCall,
|
||||||
locStub,
|
|
||||||
SSRCodegenNode,
|
|
||||||
TemplateLiteral,
|
|
||||||
IfStatement,
|
|
||||||
AssignmentExpression,
|
|
||||||
ReturnStatement,
|
|
||||||
VNodeCall,
|
|
||||||
SequenceExpression,
|
|
||||||
getVNodeBlockHelper,
|
getVNodeBlockHelper,
|
||||||
getVNodeHelper
|
getVNodeHelper,
|
||||||
|
locStub,
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import { SourceMapGenerator, RawSourceMap } from 'source-map-js'
|
import { type RawSourceMap, SourceMapGenerator } from 'source-map-js'
|
||||||
import {
|
import {
|
||||||
advancePositionWithMutation,
|
advancePositionWithMutation,
|
||||||
assert,
|
assert,
|
||||||
isSimpleIdentifier,
|
isSimpleIdentifier,
|
||||||
toValidAssetId
|
toValidAssetId,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import { isString, isArray, isSymbol } from '@vue/shared'
|
import { isArray, isString, isSymbol } from '@vue/shared'
|
||||||
import {
|
import {
|
||||||
helperNameMap,
|
CREATE_COMMENT,
|
||||||
TO_DISPLAY_STRING,
|
CREATE_ELEMENT_VNODE,
|
||||||
|
CREATE_STATIC,
|
||||||
|
CREATE_TEXT,
|
||||||
CREATE_VNODE,
|
CREATE_VNODE,
|
||||||
|
OPEN_BLOCK,
|
||||||
|
POP_SCOPE_ID,
|
||||||
|
PUSH_SCOPE_ID,
|
||||||
RESOLVE_COMPONENT,
|
RESOLVE_COMPONENT,
|
||||||
RESOLVE_DIRECTIVE,
|
RESOLVE_DIRECTIVE,
|
||||||
|
RESOLVE_FILTER,
|
||||||
SET_BLOCK_TRACKING,
|
SET_BLOCK_TRACKING,
|
||||||
CREATE_COMMENT,
|
TO_DISPLAY_STRING,
|
||||||
CREATE_TEXT,
|
|
||||||
PUSH_SCOPE_ID,
|
|
||||||
POP_SCOPE_ID,
|
|
||||||
WITH_DIRECTIVES,
|
|
||||||
CREATE_ELEMENT_VNODE,
|
|
||||||
OPEN_BLOCK,
|
|
||||||
CREATE_STATIC,
|
|
||||||
WITH_CTX,
|
WITH_CTX,
|
||||||
RESOLVE_FILTER
|
WITH_DIRECTIVES,
|
||||||
|
helperNameMap,
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { ImportItem } from './transform'
|
import type { ImportItem } from './transform'
|
||||||
|
|
||||||
const PURE_ANNOTATION = `/*#__PURE__*/`
|
const PURE_ANNOTATION = `/*#__PURE__*/`
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ enum NewlineType {
|
||||||
Start = 0,
|
Start = 0,
|
||||||
End = -1,
|
End = -1,
|
||||||
None = -2,
|
None = -2,
|
||||||
Unknown = -3
|
Unknown = -3,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CodegenContext
|
export interface CodegenContext
|
||||||
|
@ -107,8 +107,8 @@ function createCodegenContext(
|
||||||
ssrRuntimeModuleName = 'vue/server-renderer',
|
ssrRuntimeModuleName = 'vue/server-renderer',
|
||||||
ssr = false,
|
ssr = false,
|
||||||
isTS = false,
|
isTS = false,
|
||||||
inSSR = false
|
inSSR = false,
|
||||||
}: CodegenOptions
|
}: CodegenOptions,
|
||||||
): CodegenContext {
|
): CodegenContext {
|
||||||
const context: CodegenContext = {
|
const context: CodegenContext = {
|
||||||
mode,
|
mode,
|
||||||
|
@ -158,7 +158,7 @@ function createCodegenContext(
|
||||||
if (__TEST__ && code.includes('\n')) {
|
if (__TEST__ && code.includes('\n')) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`CodegenContext.push() called newlineIndex: none, but contains` +
|
`CodegenContext.push() called newlineIndex: none, but contains` +
|
||||||
`newlines: ${code.replace(/\n/g, '\\n')}`
|
`newlines: ${code.replace(/\n/g, '\\n')}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
context.column += code.length
|
context.column += code.length
|
||||||
|
@ -175,7 +175,7 @@ function createCodegenContext(
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`CodegenContext.push() called with newlineIndex: ${newlineIndex} ` +
|
`CodegenContext.push() called with newlineIndex: ${newlineIndex} ` +
|
||||||
`but does not conform: ${code.replace(/\n/g, '\\n')}`
|
`but does not conform: ${code.replace(/\n/g, '\\n')}`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
context.line++
|
context.line++
|
||||||
|
@ -199,7 +199,7 @@ function createCodegenContext(
|
||||||
},
|
},
|
||||||
newline() {
|
newline() {
|
||||||
newline(context.indentLevel)
|
newline(context.indentLevel)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function newline(n: number) {
|
function newline(n: number) {
|
||||||
|
@ -218,8 +218,8 @@ function createCodegenContext(
|
||||||
generatedLine: context.line,
|
generatedLine: context.line,
|
||||||
generatedColumn: context.column - 1,
|
generatedColumn: context.column - 1,
|
||||||
source: filename,
|
source: filename,
|
||||||
// @ts-ignore it is possible to be null
|
// @ts-expect-error it is possible to be null
|
||||||
name
|
name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ export function generate(
|
||||||
ast: RootNode,
|
ast: RootNode,
|
||||||
options: CodegenOptions & {
|
options: CodegenOptions & {
|
||||||
onContextCreated?: (context: CodegenContext) => void
|
onContextCreated?: (context: CodegenContext) => void
|
||||||
} = {}
|
} = {},
|
||||||
): CodegenResult {
|
): CodegenResult {
|
||||||
const context = createCodegenContext(ast, options)
|
const context = createCodegenContext(ast, options)
|
||||||
if (options.onContextCreated) options.onContextCreated(context)
|
if (options.onContextCreated) options.onContextCreated(context)
|
||||||
|
@ -249,7 +249,7 @@ export function generate(
|
||||||
deindent,
|
deindent,
|
||||||
newline,
|
newline,
|
||||||
scopeId,
|
scopeId,
|
||||||
ssr
|
ssr,
|
||||||
} = context
|
} = context
|
||||||
|
|
||||||
const helpers = Array.from(ast.helpers)
|
const helpers = Array.from(ast.helpers)
|
||||||
|
@ -296,7 +296,7 @@ export function generate(
|
||||||
if (hasHelpers) {
|
if (hasHelpers) {
|
||||||
push(
|
push(
|
||||||
`const { ${helpers.map(aliasHelper).join(', ')} } = _Vue\n`,
|
`const { ${helpers.map(aliasHelper).join(', ')} } = _Vue\n`,
|
||||||
NewlineType.End
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
newline()
|
newline()
|
||||||
}
|
}
|
||||||
|
@ -354,7 +354,7 @@ export function generate(
|
||||||
ast,
|
ast,
|
||||||
code: context.code,
|
code: context.code,
|
||||||
preamble: isSetupInlined ? preambleContext.code : ``,
|
preamble: isSetupInlined ? preambleContext.code : ``,
|
||||||
map: context.map ? context.map.toJSON() : undefined
|
map: context.map ? context.map.toJSON() : undefined,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,7 +366,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
|
||||||
newline,
|
newline,
|
||||||
runtimeModuleName,
|
runtimeModuleName,
|
||||||
runtimeGlobalName,
|
runtimeGlobalName,
|
||||||
ssrRuntimeModuleName
|
ssrRuntimeModuleName,
|
||||||
} = context
|
} = context
|
||||||
const VueBinding =
|
const VueBinding =
|
||||||
!__BROWSER__ && ssr
|
!__BROWSER__ && ssr
|
||||||
|
@ -381,7 +381,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
|
||||||
if (!__BROWSER__ && prefixIdentifiers) {
|
if (!__BROWSER__ && prefixIdentifiers) {
|
||||||
push(
|
push(
|
||||||
`const { ${helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`,
|
`const { ${helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`,
|
||||||
NewlineType.End
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// "with" mode.
|
// "with" mode.
|
||||||
|
@ -396,7 +396,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
|
||||||
CREATE_ELEMENT_VNODE,
|
CREATE_ELEMENT_VNODE,
|
||||||
CREATE_COMMENT,
|
CREATE_COMMENT,
|
||||||
CREATE_TEXT,
|
CREATE_TEXT,
|
||||||
CREATE_STATIC
|
CREATE_STATIC,
|
||||||
]
|
]
|
||||||
.filter(helper => helpers.includes(helper))
|
.filter(helper => helpers.includes(helper))
|
||||||
.map(aliasHelper)
|
.map(aliasHelper)
|
||||||
|
@ -412,7 +412,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
|
||||||
`const { ${ast.ssrHelpers
|
`const { ${ast.ssrHelpers
|
||||||
.map(aliasHelper)
|
.map(aliasHelper)
|
||||||
.join(', ')} } = require("${ssrRuntimeModuleName}")\n`,
|
.join(', ')} } = require("${ssrRuntimeModuleName}")\n`,
|
||||||
NewlineType.End
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
genHoists(ast.hoists, context)
|
genHoists(ast.hoists, context)
|
||||||
|
@ -424,14 +424,14 @@ function genModulePreamble(
|
||||||
ast: RootNode,
|
ast: RootNode,
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
genScopeId: boolean,
|
genScopeId: boolean,
|
||||||
inline?: boolean
|
inline?: boolean,
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
push,
|
push,
|
||||||
newline,
|
newline,
|
||||||
optimizeImports,
|
optimizeImports,
|
||||||
runtimeModuleName,
|
runtimeModuleName,
|
||||||
ssrRuntimeModuleName
|
ssrRuntimeModuleName,
|
||||||
} = context
|
} = context
|
||||||
|
|
||||||
if (genScopeId && ast.hoists.length) {
|
if (genScopeId && ast.hoists.length) {
|
||||||
|
@ -452,20 +452,20 @@ function genModulePreamble(
|
||||||
`import { ${helpers
|
`import { ${helpers
|
||||||
.map(s => helperNameMap[s])
|
.map(s => helperNameMap[s])
|
||||||
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`,
|
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`,
|
||||||
NewlineType.End
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
push(
|
push(
|
||||||
`\n// Binding optimization for webpack code-split\nconst ${helpers
|
`\n// Binding optimization for webpack code-split\nconst ${helpers
|
||||||
.map(s => `_${helperNameMap[s]} = ${helperNameMap[s]}`)
|
.map(s => `_${helperNameMap[s]} = ${helperNameMap[s]}`)
|
||||||
.join(', ')}\n`,
|
.join(', ')}\n`,
|
||||||
NewlineType.End
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
push(
|
push(
|
||||||
`import { ${helpers
|
`import { ${helpers
|
||||||
.map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
|
.map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
|
||||||
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`,
|
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`,
|
||||||
NewlineType.End
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -475,7 +475,7 @@ function genModulePreamble(
|
||||||
`import { ${ast.ssrHelpers
|
`import { ${ast.ssrHelpers
|
||||||
.map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
|
.map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
|
||||||
.join(', ')} } from "${ssrRuntimeModuleName}"\n`,
|
.join(', ')} } from "${ssrRuntimeModuleName}"\n`,
|
||||||
NewlineType.End
|
NewlineType.End,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -495,14 +495,14 @@ function genModulePreamble(
|
||||||
function genAssets(
|
function genAssets(
|
||||||
assets: string[],
|
assets: string[],
|
||||||
type: 'component' | 'directive' | 'filter',
|
type: 'component' | 'directive' | 'filter',
|
||||||
{ helper, push, newline, isTS }: CodegenContext
|
{ helper, push, newline, isTS }: CodegenContext,
|
||||||
) {
|
) {
|
||||||
const resolver = helper(
|
const resolver = helper(
|
||||||
__COMPAT__ && type === 'filter'
|
__COMPAT__ && type === 'filter'
|
||||||
? RESOLVE_FILTER
|
? RESOLVE_FILTER
|
||||||
: type === 'component'
|
: type === 'component'
|
||||||
? RESOLVE_COMPONENT
|
? RESOLVE_COMPONENT
|
||||||
: RESOLVE_DIRECTIVE
|
: RESOLVE_DIRECTIVE,
|
||||||
)
|
)
|
||||||
for (let i = 0; i < assets.length; i++) {
|
for (let i = 0; i < assets.length; i++) {
|
||||||
let id = assets[i]
|
let id = assets[i]
|
||||||
|
@ -514,7 +514,7 @@ function genAssets(
|
||||||
push(
|
push(
|
||||||
`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${
|
`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${
|
||||||
maybeSelfReference ? `, true` : ``
|
maybeSelfReference ? `, true` : ``
|
||||||
})${isTS ? `!` : ``}`
|
})${isTS ? `!` : ``}`,
|
||||||
)
|
)
|
||||||
if (i < assets.length - 1) {
|
if (i < assets.length - 1) {
|
||||||
newline()
|
newline()
|
||||||
|
@ -535,8 +535,8 @@ function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) {
|
||||||
if (genScopeId) {
|
if (genScopeId) {
|
||||||
push(
|
push(
|
||||||
`const _withScopeId = n => (${helper(
|
`const _withScopeId = n => (${helper(
|
||||||
PUSH_SCOPE_ID
|
PUSH_SCOPE_ID,
|
||||||
)}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)`
|
)}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)`,
|
||||||
)
|
)
|
||||||
newline()
|
newline()
|
||||||
}
|
}
|
||||||
|
@ -548,7 +548,7 @@ function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) {
|
||||||
push(
|
push(
|
||||||
`const _hoisted_${i + 1} = ${
|
`const _hoisted_${i + 1} = ${
|
||||||
needScopeIdWrapper ? `${PURE_ANNOTATION} _withScopeId(() => ` : ``
|
needScopeIdWrapper ? `${PURE_ANNOTATION} _withScopeId(() => ` : ``
|
||||||
}`
|
}`,
|
||||||
)
|
)
|
||||||
genNode(exp, context)
|
genNode(exp, context)
|
||||||
if (needScopeIdWrapper) {
|
if (needScopeIdWrapper) {
|
||||||
|
@ -585,7 +585,7 @@ function isText(n: string | CodegenNode) {
|
||||||
|
|
||||||
function genNodeListAsArray(
|
function genNodeListAsArray(
|
||||||
nodes: (string | CodegenNode | TemplateChildNode[])[],
|
nodes: (string | CodegenNode | TemplateChildNode[])[],
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
const multilines =
|
const multilines =
|
||||||
nodes.length > 3 ||
|
nodes.length > 3 ||
|
||||||
|
@ -601,7 +601,7 @@ function genNodeList(
|
||||||
nodes: (string | symbol | CodegenNode | TemplateChildNode[])[],
|
nodes: (string | symbol | CodegenNode | TemplateChildNode[])[],
|
||||||
context: CodegenContext,
|
context: CodegenContext,
|
||||||
multilines: boolean = false,
|
multilines: boolean = false,
|
||||||
comma: boolean = true
|
comma: boolean = true,
|
||||||
) {
|
) {
|
||||||
const { push, newline } = context
|
const { push, newline } = context
|
||||||
for (let i = 0; i < nodes.length; i++) {
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
@ -641,7 +641,7 @@ function genNode(node: CodegenNode | symbol | string, context: CodegenContext) {
|
||||||
assert(
|
assert(
|
||||||
node.codegenNode != null,
|
node.codegenNode != null,
|
||||||
`Codegen node is missing for element/if/for node. ` +
|
`Codegen node is missing for element/if/for node. ` +
|
||||||
`Apply appropriate transforms first.`
|
`Apply appropriate transforms first.`,
|
||||||
)
|
)
|
||||||
genNode(node.codegenNode!, context)
|
genNode(node.codegenNode!, context)
|
||||||
break
|
break
|
||||||
|
@ -722,7 +722,7 @@ function genNode(node: CodegenNode | symbol | string, context: CodegenContext) {
|
||||||
|
|
||||||
function genText(
|
function genText(
|
||||||
node: TextNode | SimpleExpressionNode,
|
node: TextNode | SimpleExpressionNode,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
context.push(JSON.stringify(node.content), NewlineType.Unknown, node)
|
context.push(JSON.stringify(node.content), NewlineType.Unknown, node)
|
||||||
}
|
}
|
||||||
|
@ -732,7 +732,7 @@ function genExpression(node: SimpleExpressionNode, context: CodegenContext) {
|
||||||
context.push(
|
context.push(
|
||||||
isStatic ? JSON.stringify(content) : content,
|
isStatic ? JSON.stringify(content) : content,
|
||||||
NewlineType.Unknown,
|
NewlineType.Unknown,
|
||||||
node
|
node,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -746,7 +746,7 @@ function genInterpolation(node: InterpolationNode, context: CodegenContext) {
|
||||||
|
|
||||||
function genCompoundExpression(
|
function genCompoundExpression(
|
||||||
node: CompoundExpressionNode,
|
node: CompoundExpressionNode,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
for (let i = 0; i < node.children!.length; i++) {
|
for (let i = 0; i < node.children!.length; i++) {
|
||||||
const child = node.children![i]
|
const child = node.children![i]
|
||||||
|
@ -760,7 +760,7 @@ function genCompoundExpression(
|
||||||
|
|
||||||
function genExpressionAsPropertyKey(
|
function genExpressionAsPropertyKey(
|
||||||
node: ExpressionNode,
|
node: ExpressionNode,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
const { push } = context
|
const { push } = context
|
||||||
if (node.type === NodeTypes.COMPOUND_EXPRESSION) {
|
if (node.type === NodeTypes.COMPOUND_EXPRESSION) {
|
||||||
|
@ -786,7 +786,7 @@ function genComment(node: CommentNode, context: CodegenContext) {
|
||||||
push(
|
push(
|
||||||
`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`,
|
`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`,
|
||||||
NewlineType.Unknown,
|
NewlineType.Unknown,
|
||||||
node
|
node,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,7 +801,7 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
|
||||||
directives,
|
directives,
|
||||||
isBlock,
|
isBlock,
|
||||||
disableTracking,
|
disableTracking,
|
||||||
isComponent
|
isComponent,
|
||||||
} = node
|
} = node
|
||||||
if (directives) {
|
if (directives) {
|
||||||
push(helper(WITH_DIRECTIVES) + `(`)
|
push(helper(WITH_DIRECTIVES) + `(`)
|
||||||
|
@ -818,7 +818,7 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
|
||||||
push(helper(callHelper) + `(`, NewlineType.None, node)
|
push(helper(callHelper) + `(`, NewlineType.None, node)
|
||||||
genNodeList(
|
genNodeList(
|
||||||
genNullableArgs([tag, props, children, patchFlag, dynamicProps]),
|
genNullableArgs([tag, props, children, patchFlag, dynamicProps]),
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
push(`)`)
|
push(`)`)
|
||||||
if (isBlock) {
|
if (isBlock) {
|
||||||
|
@ -887,7 +887,7 @@ function genArrayExpression(node: ArrayExpression, context: CodegenContext) {
|
||||||
|
|
||||||
function genFunctionExpression(
|
function genFunctionExpression(
|
||||||
node: FunctionExpression,
|
node: FunctionExpression,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
const { push, indent, deindent } = context
|
const { push, indent, deindent } = context
|
||||||
const { params, returns, body, newline, isSlot } = node
|
const { params, returns, body, newline, isSlot } = node
|
||||||
|
@ -932,7 +932,7 @@ function genFunctionExpression(
|
||||||
|
|
||||||
function genConditionalExpression(
|
function genConditionalExpression(
|
||||||
node: ConditionalExpression,
|
node: ConditionalExpression,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
const { test, consequent, alternate, newline: needNewline } = node
|
const { test, consequent, alternate, newline: needNewline } = node
|
||||||
const { push, indent, deindent, newline } = context
|
const { push, indent, deindent, newline } = context
|
||||||
|
@ -1033,7 +1033,7 @@ function genIfStatement(node: IfStatement, context: CodegenContext) {
|
||||||
|
|
||||||
function genAssignmentExpression(
|
function genAssignmentExpression(
|
||||||
node: AssignmentExpression,
|
node: AssignmentExpression,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
genNode(node.left, context)
|
genNode(node.left, context)
|
||||||
context.push(` = `)
|
context.push(` = `)
|
||||||
|
@ -1042,7 +1042,7 @@ function genAssignmentExpression(
|
||||||
|
|
||||||
function genSequenceExpression(
|
function genSequenceExpression(
|
||||||
node: SequenceExpression,
|
node: SequenceExpression,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
context.push(`(`)
|
context.push(`(`)
|
||||||
genNodeList(node.expressions, context)
|
genNodeList(node.expressions, context)
|
||||||
|
@ -1051,7 +1051,7 @@ function genSequenceExpression(
|
||||||
|
|
||||||
function genReturnStatement(
|
function genReturnStatement(
|
||||||
{ returns }: ReturnStatement,
|
{ returns }: ReturnStatement,
|
||||||
context: CodegenContext
|
context: CodegenContext,
|
||||||
) {
|
) {
|
||||||
context.push(`return `)
|
context.push(`return `)
|
||||||
if (isArray(returns)) {
|
if (isArray(returns)) {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { SourceLocation } from '../ast'
|
import type { SourceLocation } from '../ast'
|
||||||
import { CompilerError } from '../errors'
|
import type { CompilerError } from '../errors'
|
||||||
import { MergedParserOptions } from '../parser'
|
import type { MergedParserOptions } from '../parser'
|
||||||
import { TransformContext } from '../transform'
|
import type { TransformContext } from '../transform'
|
||||||
|
|
||||||
export type CompilerCompatConfig = Partial<
|
export type CompilerCompatConfig = Partial<
|
||||||
Record<CompilerDeprecationTypes, boolean | 'suppress-warning'>
|
Record<CompilerDeprecationTypes, boolean | 'suppress-warning'>
|
||||||
|
@ -21,7 +21,7 @@ export enum CompilerDeprecationTypes {
|
||||||
COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',
|
COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',
|
||||||
COMPILER_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',
|
COMPILER_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',
|
||||||
COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',
|
COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',
|
||||||
COMPILER_FILTERS = 'COMPILER_FILTER'
|
COMPILER_FILTERS = 'COMPILER_FILTER',
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeprecationData = {
|
type DeprecationData = {
|
||||||
|
@ -35,7 +35,7 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
||||||
`Platform-native elements with "is" prop will no longer be ` +
|
`Platform-native elements with "is" prop will no longer be ` +
|
||||||
`treated as components in Vue 3 unless the "is" value is explicitly ` +
|
`treated as components in Vue 3 unless the "is" value is explicitly ` +
|
||||||
`prefixed with "vue:".`,
|
`prefixed with "vue:".`,
|
||||||
link: `https://v3-migration.vuejs.org/breaking-changes/custom-elements-interop.html`
|
link: `https://v3-migration.vuejs.org/breaking-changes/custom-elements-interop.html`,
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_V_BIND_SYNC]: {
|
[CompilerDeprecationTypes.COMPILER_V_BIND_SYNC]: {
|
||||||
|
@ -43,7 +43,7 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
||||||
`.sync modifier for v-bind has been removed. Use v-model with ` +
|
`.sync modifier for v-bind has been removed. Use v-model with ` +
|
||||||
`argument instead. \`v-bind:${key}.sync\` should be changed to ` +
|
`argument instead. \`v-bind:${key}.sync\` should be changed to ` +
|
||||||
`\`v-model:${key}\`.`,
|
`\`v-model:${key}\`.`,
|
||||||
link: `https://v3-migration.vuejs.org/breaking-changes/v-model.html`
|
link: `https://v3-migration.vuejs.org/breaking-changes/v-model.html`,
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER]: {
|
[CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER]: {
|
||||||
|
@ -53,12 +53,12 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
||||||
`that appears before v-bind in the case of conflict. ` +
|
`that appears before v-bind in the case of conflict. ` +
|
||||||
`To retain 2.x behavior, move v-bind to make it the first attribute. ` +
|
`To retain 2.x behavior, move v-bind to make it the first attribute. ` +
|
||||||
`You can also suppress this warning if the usage is intended.`,
|
`You can also suppress this warning if the usage is intended.`,
|
||||||
link: `https://v3-migration.vuejs.org/breaking-changes/v-bind.html`
|
link: `https://v3-migration.vuejs.org/breaking-changes/v-bind.html`,
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_V_ON_NATIVE]: {
|
[CompilerDeprecationTypes.COMPILER_V_ON_NATIVE]: {
|
||||||
message: `.native modifier for v-on has been removed as is no longer necessary.`,
|
message: `.native modifier for v-on has been removed as is no longer necessary.`,
|
||||||
link: `https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html`
|
link: `https://v3-migration.vuejs.org/breaking-changes/v-on-native-modifier-removed.html`,
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE]: {
|
[CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE]: {
|
||||||
|
@ -68,18 +68,18 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
||||||
`access to v-for scope variables. It is best to avoid the ambiguity ` +
|
`access to v-for scope variables. It is best to avoid the ambiguity ` +
|
||||||
`with <template> tags or use a computed property that filters v-for ` +
|
`with <template> tags or use a computed property that filters v-for ` +
|
||||||
`data source.`,
|
`data source.`,
|
||||||
link: `https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html`
|
link: `https://v3-migration.vuejs.org/breaking-changes/v-if-v-for.html`,
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE]: {
|
[CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE]: {
|
||||||
message:
|
message:
|
||||||
`<template> with no special directives will render as a native template ` +
|
`<template> with no special directives will render as a native template ` +
|
||||||
`element instead of its inner content in Vue 3.`
|
`element instead of its inner content in Vue 3.`,
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE]: {
|
[CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE]: {
|
||||||
message: `"inline-template" has been removed in Vue 3.`,
|
message: `"inline-template" has been removed in Vue 3.`,
|
||||||
link: `https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html`
|
link: `https://v3-migration.vuejs.org/breaking-changes/inline-template-attribute.html`,
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_FILTERS]: {
|
[CompilerDeprecationTypes.COMPILER_FILTERS]: {
|
||||||
|
@ -87,13 +87,13 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
||||||
`filters have been removed in Vue 3. ` +
|
`filters have been removed in Vue 3. ` +
|
||||||
`The "|" symbol will be treated as native JavaScript bitwise OR operator. ` +
|
`The "|" symbol will be treated as native JavaScript bitwise OR operator. ` +
|
||||||
`Use method calls or computed properties instead.`,
|
`Use method calls or computed properties instead.`,
|
||||||
link: `https://v3-migration.vuejs.org/breaking-changes/filters.html`
|
link: `https://v3-migration.vuejs.org/breaking-changes/filters.html`,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCompatValue(
|
function getCompatValue(
|
||||||
key: CompilerDeprecationTypes | 'MODE',
|
key: CompilerDeprecationTypes | 'MODE',
|
||||||
{ compatConfig }: MergedParserOptions | TransformContext
|
{ compatConfig }: MergedParserOptions | TransformContext,
|
||||||
) {
|
) {
|
||||||
const value = compatConfig && compatConfig[key]
|
const value = compatConfig && compatConfig[key]
|
||||||
if (key === 'MODE') {
|
if (key === 'MODE') {
|
||||||
|
@ -105,7 +105,7 @@ function getCompatValue(
|
||||||
|
|
||||||
export function isCompatEnabled(
|
export function isCompatEnabled(
|
||||||
key: CompilerDeprecationTypes,
|
key: CompilerDeprecationTypes,
|
||||||
context: MergedParserOptions | TransformContext
|
context: MergedParserOptions | TransformContext,
|
||||||
) {
|
) {
|
||||||
const mode = getCompatValue('MODE', context)
|
const mode = getCompatValue('MODE', context)
|
||||||
const value = getCompatValue(key, context)
|
const value = getCompatValue(key, context)
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import { RESOLVE_FILTER } from '../runtimeHelpers'
|
import { RESOLVE_FILTER } from '../runtimeHelpers'
|
||||||
import {
|
import {
|
||||||
ExpressionNode,
|
type AttributeNode,
|
||||||
AttributeNode,
|
type DirectiveNode,
|
||||||
DirectiveNode,
|
type ExpressionNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
SimpleExpressionNode
|
type SimpleExpressionNode,
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import {
|
import {
|
||||||
CompilerDeprecationTypes,
|
CompilerDeprecationTypes,
|
||||||
isCompatEnabled,
|
isCompatEnabled,
|
||||||
warnDeprecation
|
warnDeprecation,
|
||||||
} from './compatConfig'
|
} from './compatConfig'
|
||||||
import { NodeTransform, TransformContext } from '../transform'
|
import type { NodeTransform, TransformContext } from '../transform'
|
||||||
import { toValidAssetId } from '../utils'
|
import { toValidAssetId } from '../utils'
|
||||||
|
|
||||||
const validDivisionCharRE = /[\w).+\-_$\]]/
|
const validDivisionCharRE = /[\w).+\-_$\]]/
|
||||||
|
@ -162,7 +162,7 @@ function parseFilter(node: SimpleExpressionNode, context: TransformContext) {
|
||||||
warnDeprecation(
|
warnDeprecation(
|
||||||
CompilerDeprecationTypes.COMPILER_FILTERS,
|
CompilerDeprecationTypes.COMPILER_FILTERS,
|
||||||
context,
|
context,
|
||||||
node.loc
|
node.loc,
|
||||||
)
|
)
|
||||||
for (i = 0; i < filters.length; i++) {
|
for (i = 0; i < filters.length; i++) {
|
||||||
expression = wrapFilter(expression, filters[i], context)
|
expression = wrapFilter(expression, filters[i], context)
|
||||||
|
@ -174,7 +174,7 @@ function parseFilter(node: SimpleExpressionNode, context: TransformContext) {
|
||||||
function wrapFilter(
|
function wrapFilter(
|
||||||
exp: string,
|
exp: string,
|
||||||
filter: string,
|
filter: string,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): string {
|
): string {
|
||||||
context.helper(RESOLVE_FILTER)
|
context.helper(RESOLVE_FILTER)
|
||||||
const i = filter.indexOf('(')
|
const i = filter.indexOf('(')
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
import { CompilerOptions } from './options'
|
import type { CompilerOptions } from './options'
|
||||||
import { baseParse } from './parser'
|
import { baseParse } from './parser'
|
||||||
import { transform, NodeTransform, DirectiveTransform } from './transform'
|
import {
|
||||||
import { generate, CodegenResult } from './codegen'
|
type DirectiveTransform,
|
||||||
import { RootNode } from './ast'
|
type NodeTransform,
|
||||||
import { isString, extend } from '@vue/shared'
|
transform,
|
||||||
|
} from './transform'
|
||||||
|
import { type CodegenResult, generate } from './codegen'
|
||||||
|
import type { RootNode } from './ast'
|
||||||
|
import { extend, isString } from '@vue/shared'
|
||||||
import { transformIf } from './transforms/vIf'
|
import { transformIf } from './transforms/vIf'
|
||||||
import { transformFor } from './transforms/vFor'
|
import { transformFor } from './transforms/vFor'
|
||||||
import { transformExpression } from './transforms/transformExpression'
|
import { transformExpression } from './transforms/transformExpression'
|
||||||
|
@ -16,16 +20,16 @@ import { transformText } from './transforms/transformText'
|
||||||
import { transformOnce } from './transforms/vOnce'
|
import { transformOnce } from './transforms/vOnce'
|
||||||
import { transformModel } from './transforms/vModel'
|
import { transformModel } from './transforms/vModel'
|
||||||
import { transformFilter } from './compat/transformFilter'
|
import { transformFilter } from './compat/transformFilter'
|
||||||
import { defaultOnError, createCompilerError, ErrorCodes } from './errors'
|
import { ErrorCodes, createCompilerError, defaultOnError } from './errors'
|
||||||
import { transformMemo } from './transforms/vMemo'
|
import { transformMemo } from './transforms/vMemo'
|
||||||
|
|
||||||
export type TransformPreset = [
|
export type TransformPreset = [
|
||||||
NodeTransform[],
|
NodeTransform[],
|
||||||
Record<string, DirectiveTransform>
|
Record<string, DirectiveTransform>,
|
||||||
]
|
]
|
||||||
|
|
||||||
export function getBaseTransformPreset(
|
export function getBaseTransformPreset(
|
||||||
prefixIdentifiers?: boolean
|
prefixIdentifiers?: boolean,
|
||||||
): TransformPreset {
|
): TransformPreset {
|
||||||
return [
|
return [
|
||||||
[
|
[
|
||||||
|
@ -38,7 +42,7 @@ export function getBaseTransformPreset(
|
||||||
? [
|
? [
|
||||||
// order is important
|
// order is important
|
||||||
trackVForSlotScopes,
|
trackVForSlotScopes,
|
||||||
transformExpression
|
transformExpression,
|
||||||
]
|
]
|
||||||
: __BROWSER__ && __DEV__
|
: __BROWSER__ && __DEV__
|
||||||
? [transformExpression]
|
? [transformExpression]
|
||||||
|
@ -46,13 +50,13 @@ export function getBaseTransformPreset(
|
||||||
transformSlotOutlet,
|
transformSlotOutlet,
|
||||||
transformElement,
|
transformElement,
|
||||||
trackSlotScopes,
|
trackSlotScopes,
|
||||||
transformText
|
transformText,
|
||||||
],
|
],
|
||||||
{
|
{
|
||||||
on: transformOn,
|
on: transformOn,
|
||||||
bind: transformBind,
|
bind: transformBind,
|
||||||
model: transformModel
|
model: transformModel,
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +64,7 @@ export function getBaseTransformPreset(
|
||||||
// @vue/compiler-dom can export `compile` while re-exporting everything else.
|
// @vue/compiler-dom can export `compile` while re-exporting everything else.
|
||||||
export function baseCompile(
|
export function baseCompile(
|
||||||
source: string | RootNode,
|
source: string | RootNode,
|
||||||
options: CompilerOptions = {}
|
options: CompilerOptions = {},
|
||||||
): CodegenResult {
|
): CodegenResult {
|
||||||
const onError = options.onError || defaultOnError
|
const onError = options.onError || defaultOnError
|
||||||
const isModuleMode = options.mode === 'module'
|
const isModuleMode = options.mode === 'module'
|
||||||
|
@ -83,7 +87,7 @@ export function baseCompile(
|
||||||
}
|
}
|
||||||
|
|
||||||
const resolvedOptions = extend({}, options, {
|
const resolvedOptions = extend({}, options, {
|
||||||
prefixIdentifiers
|
prefixIdentifiers,
|
||||||
})
|
})
|
||||||
const ast = isString(source) ? baseParse(source, resolvedOptions) : source
|
const ast = isString(source) ? baseParse(source, resolvedOptions) : source
|
||||||
const [nodeTransforms, directiveTransforms] =
|
const [nodeTransforms, directiveTransforms] =
|
||||||
|
@ -101,14 +105,14 @@ export function baseCompile(
|
||||||
extend({}, resolvedOptions, {
|
extend({}, resolvedOptions, {
|
||||||
nodeTransforms: [
|
nodeTransforms: [
|
||||||
...nodeTransforms,
|
...nodeTransforms,
|
||||||
...(options.nodeTransforms || []) // user transforms
|
...(options.nodeTransforms || []), // user transforms
|
||||||
],
|
],
|
||||||
directiveTransforms: extend(
|
directiveTransforms: extend(
|
||||||
{},
|
{},
|
||||||
directiveTransforms,
|
directiveTransforms,
|
||||||
options.directiveTransforms || {} // user transforms
|
options.directiveTransforms || {}, // user transforms
|
||||||
)
|
),
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
return generate(ast, resolvedOptions)
|
return generate(ast, resolvedOptions)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { SourceLocation } from './ast'
|
import type { SourceLocation } from './ast'
|
||||||
|
|
||||||
export interface CompilerError extends SyntaxError {
|
export interface CompilerError extends SyntaxError {
|
||||||
code: number | string
|
code: number | string
|
||||||
|
@ -25,7 +25,7 @@ export function createCompilerError<T extends number>(
|
||||||
code: T,
|
code: T,
|
||||||
loc?: SourceLocation,
|
loc?: SourceLocation,
|
||||||
messages?: { [code: number]: string },
|
messages?: { [code: number]: string },
|
||||||
additionalMessage?: string
|
additionalMessage?: string,
|
||||||
): InferCompilerError<T> {
|
): InferCompilerError<T> {
|
||||||
const msg =
|
const msg =
|
||||||
__DEV__ || !__BROWSER__
|
__DEV__ || !__BROWSER__
|
||||||
|
@ -101,7 +101,7 @@ export enum ErrorCodes {
|
||||||
// Special value for higher-order compilers to pick up the last code
|
// Special value for higher-order compilers to pick up the last code
|
||||||
// to avoid collision of error codes. This should always be kept as the last
|
// to avoid collision of error codes. This should always be kept as the last
|
||||||
// item.
|
// item.
|
||||||
__EXTEND_POINT__
|
__EXTEND_POINT__,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const errorMessages: Record<ErrorCodes, string> = {
|
export const errorMessages: Record<ErrorCodes, string> = {
|
||||||
|
@ -182,5 +182,5 @@ export const errorMessages: Record<ErrorCodes, string> = {
|
||||||
[ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED]: `"scopeId" option is only supported in module mode.`,
|
[ErrorCodes.X_SCOPE_ID_NOT_SUPPORTED]: `"scopeId" option is only supported in module mode.`,
|
||||||
|
|
||||||
// just to fulfill types
|
// just to fulfill types
|
||||||
[ErrorCodes.__EXTEND_POINT__]: ``
|
[ErrorCodes.__EXTEND_POINT__]: ``,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ export {
|
||||||
type CodegenOptions,
|
type CodegenOptions,
|
||||||
type HoistTransform,
|
type HoistTransform,
|
||||||
type BindingMetadata,
|
type BindingMetadata,
|
||||||
BindingTypes
|
BindingTypes,
|
||||||
} from './options'
|
} from './options'
|
||||||
export { baseParse } from './parser'
|
export { baseParse } from './parser'
|
||||||
export {
|
export {
|
||||||
|
@ -19,7 +19,7 @@ export {
|
||||||
createStructuralDirectiveTransform,
|
createStructuralDirectiveTransform,
|
||||||
type NodeTransform,
|
type NodeTransform,
|
||||||
type StructuralDirectiveTransform,
|
type StructuralDirectiveTransform,
|
||||||
type DirectiveTransform
|
type DirectiveTransform,
|
||||||
} from './transform'
|
} from './transform'
|
||||||
export { generate, type CodegenContext, type CodegenResult } from './codegen'
|
export { generate, type CodegenContext, type CodegenResult } from './codegen'
|
||||||
export {
|
export {
|
||||||
|
@ -27,7 +27,7 @@ export {
|
||||||
errorMessages,
|
errorMessages,
|
||||||
createCompilerError,
|
createCompilerError,
|
||||||
type CoreCompilerError,
|
type CoreCompilerError,
|
||||||
type CompilerError
|
type CompilerError,
|
||||||
} from './errors'
|
} from './errors'
|
||||||
|
|
||||||
export * from './ast'
|
export * from './ast'
|
||||||
|
@ -45,20 +45,20 @@ export { processFor, createForLoopParams } from './transforms/vFor'
|
||||||
export {
|
export {
|
||||||
transformExpression,
|
transformExpression,
|
||||||
processExpression,
|
processExpression,
|
||||||
stringifyExpression
|
stringifyExpression,
|
||||||
} from './transforms/transformExpression'
|
} from './transforms/transformExpression'
|
||||||
export {
|
export {
|
||||||
buildSlots,
|
buildSlots,
|
||||||
type SlotFnBuilder,
|
type SlotFnBuilder,
|
||||||
trackVForSlotScopes,
|
trackVForSlotScopes,
|
||||||
trackSlotScopes
|
trackSlotScopes,
|
||||||
} from './transforms/vSlot'
|
} from './transforms/vSlot'
|
||||||
export {
|
export {
|
||||||
transformElement,
|
transformElement,
|
||||||
resolveComponentType,
|
resolveComponentType,
|
||||||
buildProps,
|
buildProps,
|
||||||
buildDirectiveArgs,
|
buildDirectiveArgs,
|
||||||
type PropsExpression
|
type PropsExpression,
|
||||||
} from './transforms/transformElement'
|
} from './transforms/transformElement'
|
||||||
export { processSlotOutlet } from './transforms/transformSlotOutlet'
|
export { processSlotOutlet } from './transforms/transformSlotOutlet'
|
||||||
export { getConstantType } from './transforms/hoistStatic'
|
export { getConstantType } from './transforms/hoistStatic'
|
||||||
|
@ -68,5 +68,5 @@ export { generateCodeFrame } from '@vue/shared'
|
||||||
export {
|
export {
|
||||||
checkCompatEnabled,
|
checkCompatEnabled,
|
||||||
warnDeprecation,
|
warnDeprecation,
|
||||||
CompilerDeprecationTypes
|
CompilerDeprecationTypes,
|
||||||
} from './compat/compatConfig'
|
} from './compat/compatConfig'
|
||||||
|
|
|
@ -1,18 +1,18 @@
|
||||||
import {
|
import type {
|
||||||
ElementNode,
|
ElementNode,
|
||||||
Namespace,
|
Namespace,
|
||||||
TemplateChildNode,
|
Namespaces,
|
||||||
ParentNode,
|
ParentNode,
|
||||||
Namespaces
|
TemplateChildNode,
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import { CompilerError } from './errors'
|
import type { CompilerError } from './errors'
|
||||||
import {
|
import type {
|
||||||
NodeTransform,
|
|
||||||
DirectiveTransform,
|
DirectiveTransform,
|
||||||
TransformContext
|
NodeTransform,
|
||||||
|
TransformContext,
|
||||||
} from './transform'
|
} from './transform'
|
||||||
import { CompilerCompatOptions } from './compat/compatConfig'
|
import type { CompilerCompatOptions } from './compat/compatConfig'
|
||||||
import { ParserPlugin } from '@babel/parser'
|
import type { ParserPlugin } from '@babel/parser'
|
||||||
|
|
||||||
export interface ErrorHandlingOptions {
|
export interface ErrorHandlingOptions {
|
||||||
onWarn?: (warning: CompilerError) => void
|
onWarn?: (warning: CompilerError) => void
|
||||||
|
@ -66,7 +66,7 @@ export interface ParserOptions
|
||||||
getNamespace?: (
|
getNamespace?: (
|
||||||
tag: string,
|
tag: string,
|
||||||
parent: ElementNode | undefined,
|
parent: ElementNode | undefined,
|
||||||
rootNamespace: Namespace
|
rootNamespace: Namespace,
|
||||||
) => Namespace
|
) => Namespace
|
||||||
/**
|
/**
|
||||||
* @default ['{{', '}}']
|
* @default ['{{', '}}']
|
||||||
|
@ -102,7 +102,7 @@ export interface ParserOptions
|
||||||
export type HoistTransform = (
|
export type HoistTransform = (
|
||||||
children: TemplateChildNode[],
|
children: TemplateChildNode[],
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
parent: ParentNode
|
parent: ParentNode,
|
||||||
) => void
|
) => void
|
||||||
|
|
||||||
export enum BindingTypes {
|
export enum BindingTypes {
|
||||||
|
@ -148,7 +148,7 @@ export enum BindingTypes {
|
||||||
/**
|
/**
|
||||||
* a literal constant, e.g. 'foo', 1, true
|
* a literal constant, e.g. 'foo', 1, true
|
||||||
*/
|
*/
|
||||||
LITERAL_CONST = 'literal-const'
|
LITERAL_CONST = 'literal-const',
|
||||||
}
|
}
|
||||||
|
|
||||||
export type BindingMetadata = {
|
export type BindingMetadata = {
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import {
|
import {
|
||||||
AttributeNode,
|
type AttributeNode,
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
DirectiveNode,
|
type DirectiveNode,
|
||||||
ElementNode,
|
type ElementNode,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
ForParseResult,
|
type ForParseResult,
|
||||||
Namespaces,
|
Namespaces,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
RootNode,
|
type RootNode,
|
||||||
SimpleExpressionNode,
|
type SimpleExpressionNode,
|
||||||
SourceLocation,
|
type SourceLocation,
|
||||||
TemplateChildNode,
|
type TemplateChildNode,
|
||||||
createRoot,
|
createRoot,
|
||||||
createSimpleExpression
|
createSimpleExpression,
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import { ParserOptions } from './options'
|
import type { ParserOptions } from './options'
|
||||||
import Tokenizer, {
|
import Tokenizer, {
|
||||||
CharCodes,
|
CharCodes,
|
||||||
ParseMode,
|
ParseMode,
|
||||||
|
@ -22,33 +22,33 @@ import Tokenizer, {
|
||||||
Sequences,
|
Sequences,
|
||||||
State,
|
State,
|
||||||
isWhitespace,
|
isWhitespace,
|
||||||
toCharCodes
|
toCharCodes,
|
||||||
} from './tokenizer'
|
} from './tokenizer'
|
||||||
import {
|
import {
|
||||||
CompilerCompatOptions,
|
type CompilerCompatOptions,
|
||||||
CompilerDeprecationTypes,
|
CompilerDeprecationTypes,
|
||||||
checkCompatEnabled,
|
checkCompatEnabled,
|
||||||
isCompatEnabled,
|
isCompatEnabled,
|
||||||
warnDeprecation
|
warnDeprecation,
|
||||||
} from './compat/compatConfig'
|
} from './compat/compatConfig'
|
||||||
import { NO, extend } from '@vue/shared'
|
import { NO, extend } from '@vue/shared'
|
||||||
import {
|
import {
|
||||||
ErrorCodes,
|
ErrorCodes,
|
||||||
createCompilerError,
|
createCompilerError,
|
||||||
defaultOnError,
|
defaultOnError,
|
||||||
defaultOnWarn
|
defaultOnWarn,
|
||||||
} from './errors'
|
} from './errors'
|
||||||
import {
|
import {
|
||||||
forAliasRE,
|
forAliasRE,
|
||||||
isCoreComponent,
|
isCoreComponent,
|
||||||
isSimpleIdentifier,
|
isSimpleIdentifier,
|
||||||
isStaticArgOf
|
isStaticArgOf,
|
||||||
} from './utils'
|
} from './utils'
|
||||||
import { decodeHTML } from 'entities/lib/decode.js'
|
import { decodeHTML } from 'entities/lib/decode.js'
|
||||||
import {
|
import {
|
||||||
|
type ParserOptions as BabelOptions,
|
||||||
parse,
|
parse,
|
||||||
parseExpression,
|
parseExpression,
|
||||||
type ParserOptions as BabelOptions
|
|
||||||
} from '@babel/parser'
|
} from '@babel/parser'
|
||||||
|
|
||||||
type OptionalOptions =
|
type OptionalOptions =
|
||||||
|
@ -76,7 +76,7 @@ export const defaultParserOptions: MergedParserOptions = {
|
||||||
onError: defaultOnError,
|
onError: defaultOnError,
|
||||||
onWarn: defaultOnWarn,
|
onWarn: defaultOnWarn,
|
||||||
comments: __DEV__,
|
comments: __DEV__,
|
||||||
prefixIdentifiers: false
|
prefixIdentifiers: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
let currentOptions: MergedParserOptions = defaultParserOptions
|
let currentOptions: MergedParserOptions = defaultParserOptions
|
||||||
|
@ -129,7 +129,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
addNode({
|
addNode({
|
||||||
type: NodeTypes.INTERPOLATION,
|
type: NodeTypes.INTERPOLATION,
|
||||||
content: createExp(exp, false, getLoc(innerStart, innerEnd)),
|
content: createExp(exp, false, getLoc(innerStart, innerEnd)),
|
||||||
loc: getLoc(start, end)
|
loc: getLoc(start, end),
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
props: [],
|
props: [],
|
||||||
children: [],
|
children: [],
|
||||||
loc: getLoc(start - 1, end),
|
loc: getLoc(start - 1, end),
|
||||||
codegenNode: undefined
|
codegenNode: undefined,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
name: getSlice(start, end),
|
name: getSlice(start, end),
|
||||||
nameLoc: getLoc(start, end),
|
nameLoc: getLoc(start, end),
|
||||||
value: undefined,
|
value: undefined,
|
||||||
loc: getLoc(start)
|
loc: getLoc(start),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -216,7 +216,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
name: raw,
|
name: raw,
|
||||||
nameLoc: getLoc(start, end),
|
nameLoc: getLoc(start, end),
|
||||||
value: undefined,
|
value: undefined,
|
||||||
loc: getLoc(start)
|
loc: getLoc(start),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
currentProp = {
|
currentProp = {
|
||||||
|
@ -226,7 +226,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
exp: undefined,
|
exp: undefined,
|
||||||
arg: undefined,
|
arg: undefined,
|
||||||
modifiers: raw === '.' ? ['prop'] : [],
|
modifiers: raw === '.' ? ['prop'] : [],
|
||||||
loc: getLoc(start)
|
loc: getLoc(start),
|
||||||
}
|
}
|
||||||
if (name === 'pre') {
|
if (name === 'pre') {
|
||||||
inVPre = tokenizer.inVPre = true
|
inVPre = tokenizer.inVPre = true
|
||||||
|
@ -254,7 +254,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
isStatic ? arg : arg.slice(1, -1),
|
isStatic ? arg : arg.slice(1, -1),
|
||||||
isStatic,
|
isStatic,
|
||||||
getLoc(start, end),
|
getLoc(start, end),
|
||||||
isStatic ? ConstantTypes.CAN_STRINGIFY : ConstantTypes.NOT_CONSTANT
|
isStatic ? ConstantTypes.CAN_STRINGIFY : ConstantTypes.NOT_CONSTANT,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -298,7 +298,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
// check duplicate attrs
|
// check duplicate attrs
|
||||||
if (
|
if (
|
||||||
currentOpenTag!.props.some(
|
currentOpenTag!.props.some(
|
||||||
p => (p.type === NodeTypes.DIRECTIVE ? p.rawName : p.name) === name
|
p => (p.type === NodeTypes.DIRECTIVE ? p.rawName : p.name) === name,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
emitError(ErrorCodes.DUPLICATE_ATTRIBUTE, start)
|
emitError(ErrorCodes.DUPLICATE_ATTRIBUTE, start)
|
||||||
|
@ -314,7 +314,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
if (__BROWSER__ && currentAttrValue.includes('&')) {
|
if (__BROWSER__ && currentAttrValue.includes('&')) {
|
||||||
currentAttrValue = currentOptions.decodeEntities!(
|
currentAttrValue = currentOptions.decodeEntities!(
|
||||||
currentAttrValue,
|
currentAttrValue,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
loc:
|
loc:
|
||||||
quote === QuoteType.Unquoted
|
quote === QuoteType.Unquoted
|
||||||
? getLoc(currentAttrStartIndex, currentAttrEndIndex)
|
? getLoc(currentAttrStartIndex, currentAttrEndIndex)
|
||||||
: getLoc(currentAttrStartIndex - 1, currentAttrEndIndex + 1)
|
: getLoc(currentAttrStartIndex - 1, currentAttrEndIndex + 1),
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
tokenizer.inSFCRoot &&
|
tokenizer.inSFCRoot &&
|
||||||
|
@ -369,7 +369,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
false,
|
false,
|
||||||
getLoc(currentAttrStartIndex, currentAttrEndIndex),
|
getLoc(currentAttrStartIndex, currentAttrEndIndex),
|
||||||
ConstantTypes.NOT_CONSTANT,
|
ConstantTypes.NOT_CONSTANT,
|
||||||
expParseMode
|
expParseMode,
|
||||||
)
|
)
|
||||||
if (currentProp.name === 'for') {
|
if (currentProp.name === 'for') {
|
||||||
currentProp.forParseResult = parseForExpression(currentProp.exp)
|
currentProp.forParseResult = parseForExpression(currentProp.exp)
|
||||||
|
@ -384,7 +384,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
CompilerDeprecationTypes.COMPILER_V_BIND_SYNC,
|
CompilerDeprecationTypes.COMPILER_V_BIND_SYNC,
|
||||||
currentOptions,
|
currentOptions,
|
||||||
currentProp.loc,
|
currentProp.loc,
|
||||||
currentProp.rawName
|
currentProp.rawName,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
currentProp.name = 'model'
|
currentProp.name = 'model'
|
||||||
|
@ -408,7 +408,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
addNode({
|
addNode({
|
||||||
type: NodeTypes.COMMENT,
|
type: NodeTypes.COMMENT,
|
||||||
content: getSlice(start, end),
|
content: getSlice(start, end),
|
||||||
loc: getLoc(start - 4, end + 3)
|
loc: getLoc(start - 4, end + 3),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -426,7 +426,7 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
case State.InterpolationClose:
|
case State.InterpolationClose:
|
||||||
emitError(
|
emitError(
|
||||||
ErrorCodes.X_MISSING_INTERPOLATION_END,
|
ErrorCodes.X_MISSING_INTERPOLATION_END,
|
||||||
tokenizer.sectionStart
|
tokenizer.sectionStart,
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
case State.InCommentLike:
|
case State.InCommentLike:
|
||||||
|
@ -476,10 +476,10 @@ const tokenizer = new Tokenizer(stack, {
|
||||||
if ((stack[0] ? stack[0].ns : currentOptions.ns) === Namespaces.HTML) {
|
if ((stack[0] ? stack[0].ns : currentOptions.ns) === Namespaces.HTML) {
|
||||||
emitError(
|
emitError(
|
||||||
ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
|
ErrorCodes.UNEXPECTED_QUESTION_MARK_INSTEAD_OF_TAG_NAME,
|
||||||
start - 1
|
start - 1,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// This regex doesn't cover the case if key or index aliases have destructuring,
|
// This regex doesn't cover the case if key or index aliases have destructuring,
|
||||||
|
@ -488,7 +488,7 @@ const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
|
||||||
const stripParensRE = /^\(|\)$/g
|
const stripParensRE = /^\(|\)$/g
|
||||||
|
|
||||||
function parseForExpression(
|
function parseForExpression(
|
||||||
input: SimpleExpressionNode
|
input: SimpleExpressionNode,
|
||||||
): ForParseResult | undefined {
|
): ForParseResult | undefined {
|
||||||
const loc = input.loc
|
const loc = input.loc
|
||||||
const exp = input.content
|
const exp = input.content
|
||||||
|
@ -500,7 +500,7 @@ function parseForExpression(
|
||||||
const createAliasExpression = (
|
const createAliasExpression = (
|
||||||
content: string,
|
content: string,
|
||||||
offset: number,
|
offset: number,
|
||||||
asParam = false
|
asParam = false,
|
||||||
) => {
|
) => {
|
||||||
const start = loc.start.offset + offset
|
const start = loc.start.offset + offset
|
||||||
const end = start + content.length
|
const end = start + content.length
|
||||||
|
@ -509,7 +509,7 @@ function parseForExpression(
|
||||||
false,
|
false,
|
||||||
getLoc(start, end),
|
getLoc(start, end),
|
||||||
ConstantTypes.NOT_CONSTANT,
|
ConstantTypes.NOT_CONSTANT,
|
||||||
asParam ? ExpParseMode.Params : ExpParseMode.Normal
|
asParam ? ExpParseMode.Params : ExpParseMode.Normal,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,7 +518,7 @@ function parseForExpression(
|
||||||
value: undefined,
|
value: undefined,
|
||||||
key: undefined,
|
key: undefined,
|
||||||
index: undefined,
|
index: undefined,
|
||||||
finalized: false
|
finalized: false,
|
||||||
}
|
}
|
||||||
|
|
||||||
let valueContent = LHS.trim().replace(stripParensRE, '').trim()
|
let valueContent = LHS.trim().replace(stripParensRE, '').trim()
|
||||||
|
@ -545,9 +545,9 @@ function parseForExpression(
|
||||||
indexContent,
|
indexContent,
|
||||||
result.key
|
result.key
|
||||||
? keyOffset! + keyContent.length
|
? keyOffset! + keyContent.length
|
||||||
: trimmedOffset + valueContent.length
|
: trimmedOffset + valueContent.length,
|
||||||
),
|
),
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -602,7 +602,7 @@ function onText(content: string, start: number, end: number) {
|
||||||
parent.children.push({
|
parent.children.push({
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content,
|
content,
|
||||||
loc: getLoc(start, end)
|
loc: getLoc(start, end),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -625,7 +625,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
||||||
}
|
}
|
||||||
el.innerLoc!.source = getSlice(
|
el.innerLoc!.source = getSlice(
|
||||||
el.innerLoc!.start.offset,
|
el.innerLoc!.start.offset,
|
||||||
el.innerLoc!.end.offset
|
el.innerLoc!.end.offset,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -666,7 +666,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
||||||
__DEV__ &&
|
__DEV__ &&
|
||||||
isCompatEnabled(
|
isCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,
|
CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,
|
||||||
currentOptions
|
currentOptions,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
let hasIf = false
|
let hasIf = false
|
||||||
|
@ -684,7 +684,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
||||||
warnDeprecation(
|
warnDeprecation(
|
||||||
CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,
|
CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,
|
||||||
currentOptions,
|
currentOptions,
|
||||||
el.loc
|
el.loc,
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -694,7 +694,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
||||||
if (
|
if (
|
||||||
isCompatEnabled(
|
isCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,
|
CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,
|
||||||
currentOptions
|
currentOptions,
|
||||||
) &&
|
) &&
|
||||||
el.tag === 'template' &&
|
el.tag === 'template' &&
|
||||||
!isFragmentTemplate(el)
|
!isFragmentTemplate(el)
|
||||||
|
@ -703,7 +703,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
||||||
warnDeprecation(
|
warnDeprecation(
|
||||||
CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,
|
CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,
|
||||||
currentOptions,
|
currentOptions,
|
||||||
el.loc
|
el.loc,
|
||||||
)
|
)
|
||||||
// unwrap
|
// unwrap
|
||||||
const parent = stack[0] || currentRoot
|
const parent = stack[0] || currentRoot
|
||||||
|
@ -712,14 +712,14 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const inlineTemplateProp = props.find(
|
const inlineTemplateProp = props.find(
|
||||||
p => p.type === NodeTypes.ATTRIBUTE && p.name === 'inline-template'
|
p => p.type === NodeTypes.ATTRIBUTE && p.name === 'inline-template',
|
||||||
) as AttributeNode
|
) as AttributeNode
|
||||||
if (
|
if (
|
||||||
inlineTemplateProp &&
|
inlineTemplateProp &&
|
||||||
checkCompatEnabled(
|
checkCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE,
|
CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE,
|
||||||
currentOptions,
|
currentOptions,
|
||||||
inlineTemplateProp.loc
|
inlineTemplateProp.loc,
|
||||||
) &&
|
) &&
|
||||||
el.children.length
|
el.children.length
|
||||||
) {
|
) {
|
||||||
|
@ -727,9 +727,9 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: getSlice(
|
content: getSlice(
|
||||||
el.children[0].loc.start.offset,
|
el.children[0].loc.start.offset,
|
||||||
el.children[el.children.length - 1].loc.end.offset
|
el.children[el.children.length - 1].loc.end.offset,
|
||||||
),
|
),
|
||||||
loc: inlineTemplateProp.loc
|
loc: inlineTemplateProp.loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -782,7 +782,7 @@ function isComponent({ tag, props }: ElementNode): boolean {
|
||||||
checkCompatEnabled(
|
checkCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||||
currentOptions,
|
currentOptions,
|
||||||
p.loc
|
p.loc,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
|
@ -796,7 +796,7 @@ function isComponent({ tag, props }: ElementNode): boolean {
|
||||||
checkCompatEnabled(
|
checkCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||||
currentOptions,
|
currentOptions,
|
||||||
p.loc
|
p.loc,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return true
|
return true
|
||||||
|
@ -812,7 +812,7 @@ function isUpperCase(c: number) {
|
||||||
const windowsNewlineRE = /\r\n/g
|
const windowsNewlineRE = /\r\n/g
|
||||||
function condenseWhitespace(
|
function condenseWhitespace(
|
||||||
nodes: TemplateChildNode[],
|
nodes: TemplateChildNode[],
|
||||||
tag?: string
|
tag?: string,
|
||||||
): TemplateChildNode[] {
|
): TemplateChildNode[] {
|
||||||
const shouldCondense = currentOptions.whitespace !== 'preserve'
|
const shouldCondense = currentOptions.whitespace !== 'preserve'
|
||||||
let removedWhitespace = false
|
let removedWhitespace = false
|
||||||
|
@ -915,7 +915,7 @@ function getLoc(start: number, end?: number): SourceLocation {
|
||||||
// @ts-expect-error allow late attachment
|
// @ts-expect-error allow late attachment
|
||||||
end: end == null ? end : tokenizer.getPos(end),
|
end: end == null ? end : tokenizer.getPos(end),
|
||||||
// @ts-expect-error allow late attachment
|
// @ts-expect-error allow late attachment
|
||||||
source: end == null ? end : getSlice(start, end)
|
source: end == null ? end : getSlice(start, end),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -930,10 +930,10 @@ function dirToAttr(dir: DirectiveNode): AttributeNode {
|
||||||
name: dir.rawName!,
|
name: dir.rawName!,
|
||||||
nameLoc: getLoc(
|
nameLoc: getLoc(
|
||||||
dir.loc.start.offset,
|
dir.loc.start.offset,
|
||||||
dir.loc.start.offset + dir.rawName!.length
|
dir.loc.start.offset + dir.rawName!.length,
|
||||||
),
|
),
|
||||||
value: undefined,
|
value: undefined,
|
||||||
loc: dir.loc
|
loc: dir.loc,
|
||||||
}
|
}
|
||||||
if (dir.exp) {
|
if (dir.exp) {
|
||||||
// account for quotes
|
// account for quotes
|
||||||
|
@ -947,7 +947,7 @@ function dirToAttr(dir: DirectiveNode): AttributeNode {
|
||||||
attr.value = {
|
attr.value = {
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: (dir.exp as SimpleExpressionNode).content,
|
content: (dir.exp as SimpleExpressionNode).content,
|
||||||
loc
|
loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return attr
|
return attr
|
||||||
|
@ -957,7 +957,7 @@ enum ExpParseMode {
|
||||||
Normal,
|
Normal,
|
||||||
Params,
|
Params,
|
||||||
Statements,
|
Statements,
|
||||||
Skip
|
Skip,
|
||||||
}
|
}
|
||||||
|
|
||||||
function createExp(
|
function createExp(
|
||||||
|
@ -965,7 +965,7 @@ function createExp(
|
||||||
isStatic: SimpleExpressionNode['isStatic'] = false,
|
isStatic: SimpleExpressionNode['isStatic'] = false,
|
||||||
loc: SourceLocation,
|
loc: SourceLocation,
|
||||||
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT,
|
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT,
|
||||||
parseMode = ExpParseMode.Normal
|
parseMode = ExpParseMode.Normal,
|
||||||
) {
|
) {
|
||||||
const exp = createSimpleExpression(content, isStatic, loc, constType)
|
const exp = createSimpleExpression(content, isStatic, loc, constType)
|
||||||
if (
|
if (
|
||||||
|
@ -982,7 +982,7 @@ function createExp(
|
||||||
try {
|
try {
|
||||||
const plugins = currentOptions.expressionPlugins
|
const plugins = currentOptions.expressionPlugins
|
||||||
const options: BabelOptions = {
|
const options: BabelOptions = {
|
||||||
plugins: plugins ? [...plugins, 'typescript'] : ['typescript']
|
plugins: plugins ? [...plugins, 'typescript'] : ['typescript'],
|
||||||
}
|
}
|
||||||
if (parseMode === ExpParseMode.Statements) {
|
if (parseMode === ExpParseMode.Statements) {
|
||||||
// v-on with multi-inline-statements, pad 1 char
|
// v-on with multi-inline-statements, pad 1 char
|
||||||
|
@ -1003,7 +1003,7 @@ function createExp(
|
||||||
|
|
||||||
function emitError(code: ErrorCodes, index: number, message?: string) {
|
function emitError(code: ErrorCodes, index: number, message?: string) {
|
||||||
currentOptions.onError(
|
currentOptions.onError(
|
||||||
createCompilerError(code, getLoc(index, index), undefined, message)
|
createCompilerError(code, getLoc(index, index), undefined, message),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1026,7 +1026,7 @@ export function baseParse(input: string, options?: ParserOptions): RootNode {
|
||||||
let key: keyof ParserOptions
|
let key: keyof ParserOptions
|
||||||
for (key in options) {
|
for (key in options) {
|
||||||
if (options[key] != null) {
|
if (options[key] != null) {
|
||||||
// @ts-ignore
|
// @ts-expect-error
|
||||||
currentOptions[key] = options[key]
|
currentOptions[key] = options[key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1036,11 +1036,11 @@ export function baseParse(input: string, options?: ParserOptions): RootNode {
|
||||||
if (!__BROWSER__ && currentOptions.decodeEntities) {
|
if (!__BROWSER__ && currentOptions.decodeEntities) {
|
||||||
console.warn(
|
console.warn(
|
||||||
`[@vue/compiler-core] decodeEntities option is passed but will be ` +
|
`[@vue/compiler-core] decodeEntities option is passed but will be ` +
|
||||||
`ignored in non-browser builds.`
|
`ignored in non-browser builds.`,
|
||||||
)
|
)
|
||||||
} else if (__BROWSER__ && !currentOptions.decodeEntities) {
|
} else if (__BROWSER__ && !currentOptions.decodeEntities) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`[@vue/compiler-core] decodeEntities option is required in browser builds.`
|
`[@vue/compiler-core] decodeEntities option is required in browser builds.`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const CREATE_TEXT = Symbol(__DEV__ ? `createTextVNode` : ``)
|
||||||
export const CREATE_STATIC = Symbol(__DEV__ ? `createStaticVNode` : ``)
|
export const CREATE_STATIC = Symbol(__DEV__ ? `createStaticVNode` : ``)
|
||||||
export const RESOLVE_COMPONENT = Symbol(__DEV__ ? `resolveComponent` : ``)
|
export const RESOLVE_COMPONENT = Symbol(__DEV__ ? `resolveComponent` : ``)
|
||||||
export const RESOLVE_DYNAMIC_COMPONENT = Symbol(
|
export const RESOLVE_DYNAMIC_COMPONENT = Symbol(
|
||||||
__DEV__ ? `resolveDynamicComponent` : ``
|
__DEV__ ? `resolveDynamicComponent` : ``,
|
||||||
)
|
)
|
||||||
export const RESOLVE_DIRECTIVE = Symbol(__DEV__ ? `resolveDirective` : ``)
|
export const RESOLVE_DIRECTIVE = Symbol(__DEV__ ? `resolveDirective` : ``)
|
||||||
export const RESOLVE_FILTER = Symbol(__DEV__ ? `resolveFilter` : ``)
|
export const RESOLVE_FILTER = Symbol(__DEV__ ? `resolveFilter` : ``)
|
||||||
|
@ -81,7 +81,7 @@ export const helperNameMap: Record<symbol, string> = {
|
||||||
[UNREF]: `unref`,
|
[UNREF]: `unref`,
|
||||||
[IS_REF]: `isRef`,
|
[IS_REF]: `isRef`,
|
||||||
[WITH_MEMO]: `withMemo`,
|
[WITH_MEMO]: `withMemo`,
|
||||||
[IS_MEMO_SAME]: `isMemoSame`
|
[IS_MEMO_SAME]: `isMemoSame`,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function registerRuntimeHelpers(helpers: Record<symbol, string>) {
|
export function registerRuntimeHelpers(helpers: Record<symbol, string>) {
|
||||||
|
|
|
@ -23,7 +23,7 @@ IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ErrorCodes } from './errors'
|
import { ErrorCodes } from './errors'
|
||||||
import { ElementNode, Position } from './ast'
|
import type { ElementNode, Position } from './ast'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: entities is a non-browser-build-only dependency.
|
* Note: entities is a non-browser-build-only dependency.
|
||||||
|
@ -32,16 +32,16 @@ import { ElementNode, Position } from './ast'
|
||||||
* so that it can be properly treeshaken.
|
* so that it can be properly treeshaken.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
EntityDecoder,
|
|
||||||
DecodingMode,
|
DecodingMode,
|
||||||
|
EntityDecoder,
|
||||||
|
fromCodePoint,
|
||||||
htmlDecodeTree,
|
htmlDecodeTree,
|
||||||
fromCodePoint
|
|
||||||
} from 'entities/lib/decode.js'
|
} from 'entities/lib/decode.js'
|
||||||
|
|
||||||
export enum ParseMode {
|
export enum ParseMode {
|
||||||
BASE,
|
BASE,
|
||||||
HTML,
|
HTML,
|
||||||
SFC
|
SFC,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum CharCodes {
|
export enum CharCodes {
|
||||||
|
@ -77,7 +77,7 @@ export enum CharCodes {
|
||||||
Colon = 0x3a, // ":"
|
Colon = 0x3a, // ":"
|
||||||
At = 0x40, // "@"
|
At = 0x40, // "@"
|
||||||
LeftSquare = 91, // "["
|
LeftSquare = 91, // "["
|
||||||
RightSquare = 93 // "]"
|
RightSquare = 93, // "]"
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultDelimitersOpen = new Uint8Array([123, 123]) // "{{"
|
const defaultDelimitersOpen = new Uint8Array([123, 123]) // "{{"
|
||||||
|
@ -134,7 +134,7 @@ export enum State {
|
||||||
|
|
||||||
InEntity,
|
InEntity,
|
||||||
|
|
||||||
InSFCRootTagName
|
InSFCRootTagName,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,7 +174,7 @@ export enum QuoteType {
|
||||||
NoValue = 0,
|
NoValue = 0,
|
||||||
Unquoted = 1,
|
Unquoted = 1,
|
||||||
Single = 2,
|
Single = 2,
|
||||||
Double = 3
|
Double = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Callbacks {
|
export interface Callbacks {
|
||||||
|
@ -221,8 +221,8 @@ export const Sequences = {
|
||||||
StyleEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65]), // `</style`
|
StyleEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65]), // `</style`
|
||||||
TitleEnd: new Uint8Array([0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65]), // `</title`
|
TitleEnd: new Uint8Array([0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65]), // `</title`
|
||||||
TextareaEnd: new Uint8Array([
|
TextareaEnd: new Uint8Array([
|
||||||
0x3c, 0x2f, 116, 101, 120, 116, 97, 114, 101, 97
|
0x3c, 0x2f, 116, 101, 120, 116, 97, 114, 101, 97,
|
||||||
]) // `</textarea
|
]), // `</textarea
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class Tokenizer {
|
export default class Tokenizer {
|
||||||
|
@ -256,11 +256,11 @@ export default class Tokenizer {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private readonly stack: ElementNode[],
|
private readonly stack: ElementNode[],
|
||||||
private readonly cbs: Callbacks
|
private readonly cbs: Callbacks,
|
||||||
) {
|
) {
|
||||||
if (!__BROWSER__) {
|
if (!__BROWSER__) {
|
||||||
this.entityDecoder = new EntityDecoder(htmlDecodeTree, (cp, consumed) =>
|
this.entityDecoder = new EntityDecoder(htmlDecodeTree, (cp, consumed) =>
|
||||||
this.emitCodePoint(cp, consumed)
|
this.emitCodePoint(cp, consumed),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,7 +299,7 @@ export default class Tokenizer {
|
||||||
return {
|
return {
|
||||||
column,
|
column,
|
||||||
line,
|
line,
|
||||||
offset: index
|
offset: index,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -647,7 +647,7 @@ export default class Tokenizer {
|
||||||
if ((__DEV__ || !__BROWSER__) && c === CharCodes.Eq) {
|
if ((__DEV__ || !__BROWSER__) && c === CharCodes.Eq) {
|
||||||
this.cbs.onerr(
|
this.cbs.onerr(
|
||||||
ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
|
ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
|
||||||
this.index
|
this.index,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
this.handleAttrStart(c)
|
this.handleAttrStart(c)
|
||||||
|
@ -694,7 +694,7 @@ export default class Tokenizer {
|
||||||
) {
|
) {
|
||||||
this.cbs.onerr(
|
this.cbs.onerr(
|
||||||
ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
|
ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
|
||||||
this.index
|
this.index,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -733,7 +733,7 @@ export default class Tokenizer {
|
||||||
if (__DEV__ || !__BROWSER__) {
|
if (__DEV__ || !__BROWSER__) {
|
||||||
this.cbs.onerr(
|
this.cbs.onerr(
|
||||||
ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,
|
ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,
|
||||||
this.index
|
this.index,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -785,7 +785,7 @@ export default class Tokenizer {
|
||||||
this.sectionStart = -1
|
this.sectionStart = -1
|
||||||
this.cbs.onattribend(
|
this.cbs.onattribend(
|
||||||
quote === CharCodes.DoubleQuote ? QuoteType.Double : QuoteType.Single,
|
quote === CharCodes.DoubleQuote ? QuoteType.Double : QuoteType.Single,
|
||||||
this.index + 1
|
this.index + 1,
|
||||||
)
|
)
|
||||||
this.state = State.BeforeAttrName
|
this.state = State.BeforeAttrName
|
||||||
} else if (!__BROWSER__ && c === CharCodes.Amp) {
|
} else if (!__BROWSER__ && c === CharCodes.Amp) {
|
||||||
|
@ -814,7 +814,7 @@ export default class Tokenizer {
|
||||||
) {
|
) {
|
||||||
this.cbs.onerr(
|
this.cbs.onerr(
|
||||||
ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
|
ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
|
||||||
this.index
|
this.index,
|
||||||
)
|
)
|
||||||
} else if (!__BROWSER__ && c === CharCodes.Amp) {
|
} else if (!__BROWSER__ && c === CharCodes.Amp) {
|
||||||
this.startEntity()
|
this.startEntity()
|
||||||
|
@ -892,7 +892,7 @@ export default class Tokenizer {
|
||||||
this.entityDecoder!.startEntity(
|
this.entityDecoder!.startEntity(
|
||||||
this.baseState === State.Text || this.baseState === State.InRCDATA
|
this.baseState === State.Text || this.baseState === State.InRCDATA
|
||||||
? DecodingMode.Legacy
|
? DecodingMode.Legacy
|
||||||
: DecodingMode.Attribute
|
: DecodingMode.Attribute,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1156,7 +1156,7 @@ export default class Tokenizer {
|
||||||
this.cbs.onattribentity(
|
this.cbs.onattribentity(
|
||||||
fromCodePoint(cp),
|
fromCodePoint(cp),
|
||||||
this.entityStart,
|
this.entityStart,
|
||||||
this.sectionStart
|
this.sectionStart,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
if (this.sectionStart < this.entityStart) {
|
if (this.sectionStart < this.entityStart) {
|
||||||
|
@ -1168,7 +1168,7 @@ export default class Tokenizer {
|
||||||
this.cbs.ontextentity(
|
this.cbs.ontextentity(
|
||||||
fromCodePoint(cp),
|
fromCodePoint(cp),
|
||||||
this.entityStart,
|
this.entityStart,
|
||||||
this.sectionStart
|
this.sectionStart,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
import { TransformOptions } from './options'
|
import type { TransformOptions } from './options'
|
||||||
import {
|
import {
|
||||||
RootNode,
|
type ArrayExpression,
|
||||||
NodeTypes,
|
type CacheExpression,
|
||||||
ParentNode,
|
|
||||||
TemplateChildNode,
|
|
||||||
ElementNode,
|
|
||||||
DirectiveNode,
|
|
||||||
Property,
|
|
||||||
ExpressionNode,
|
|
||||||
createSimpleExpression,
|
|
||||||
JSChildNode,
|
|
||||||
SimpleExpressionNode,
|
|
||||||
ElementTypes,
|
|
||||||
CacheExpression,
|
|
||||||
createCacheExpression,
|
|
||||||
TemplateLiteral,
|
|
||||||
createVNodeCall,
|
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
ArrayExpression,
|
type DirectiveNode,
|
||||||
convertToBlock
|
type ElementNode,
|
||||||
|
ElementTypes,
|
||||||
|
type ExpressionNode,
|
||||||
|
type JSChildNode,
|
||||||
|
NodeTypes,
|
||||||
|
type ParentNode,
|
||||||
|
type Property,
|
||||||
|
type RootNode,
|
||||||
|
type SimpleExpressionNode,
|
||||||
|
type TemplateChildNode,
|
||||||
|
type TemplateLiteral,
|
||||||
|
convertToBlock,
|
||||||
|
createCacheExpression,
|
||||||
|
createSimpleExpression,
|
||||||
|
createVNodeCall,
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import {
|
import {
|
||||||
isString,
|
|
||||||
isArray,
|
|
||||||
NOOP,
|
|
||||||
PatchFlags,
|
|
||||||
PatchFlagNames,
|
|
||||||
EMPTY_OBJ,
|
EMPTY_OBJ,
|
||||||
|
NOOP,
|
||||||
|
PatchFlagNames,
|
||||||
|
PatchFlags,
|
||||||
|
camelize,
|
||||||
capitalize,
|
capitalize,
|
||||||
camelize
|
isArray,
|
||||||
|
isString,
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { defaultOnError, defaultOnWarn } from './errors'
|
import { defaultOnError, defaultOnWarn } from './errors'
|
||||||
import {
|
import {
|
||||||
TO_DISPLAY_STRING,
|
CREATE_COMMENT,
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
|
TO_DISPLAY_STRING,
|
||||||
helperNameMap,
|
helperNameMap,
|
||||||
CREATE_COMMENT
|
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { isVSlot } from './utils'
|
import { isVSlot } from './utils'
|
||||||
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
|
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
|
||||||
import { CompilerCompatOptions } from './compat/compatConfig'
|
import type { CompilerCompatOptions } from './compat/compatConfig'
|
||||||
|
|
||||||
// There are two types of transforms:
|
// There are two types of transforms:
|
||||||
//
|
//
|
||||||
|
@ -48,7 +48,7 @@ import { CompilerCompatOptions } from './compat/compatConfig'
|
||||||
// replace or remove the node being processed.
|
// replace or remove the node being processed.
|
||||||
export type NodeTransform = (
|
export type NodeTransform = (
|
||||||
node: RootNode | TemplateChildNode,
|
node: RootNode | TemplateChildNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
) => void | (() => void) | (() => void)[]
|
) => void | (() => void) | (() => void)[]
|
||||||
|
|
||||||
// - DirectiveTransform:
|
// - DirectiveTransform:
|
||||||
|
@ -60,7 +60,7 @@ export type DirectiveTransform = (
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
// a platform specific compiler can import the base transform and augment
|
// a platform specific compiler can import the base transform and augment
|
||||||
// it by passing in this optional argument.
|
// it by passing in this optional argument.
|
||||||
augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult
|
augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult,
|
||||||
) => DirectiveTransformResult
|
) => DirectiveTransformResult
|
||||||
|
|
||||||
export interface DirectiveTransformResult {
|
export interface DirectiveTransformResult {
|
||||||
|
@ -74,7 +74,7 @@ export interface DirectiveTransformResult {
|
||||||
export type StructuralDirectiveTransform = (
|
export type StructuralDirectiveTransform = (
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
dir: DirectiveNode,
|
dir: DirectiveNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
) => void | (() => void)
|
) => void | (() => void)
|
||||||
|
|
||||||
export interface ImportItem {
|
export interface ImportItem {
|
||||||
|
@ -145,8 +145,8 @@ export function createTransformContext(
|
||||||
isTS = false,
|
isTS = false,
|
||||||
onError = defaultOnError,
|
onError = defaultOnError,
|
||||||
onWarn = defaultOnWarn,
|
onWarn = defaultOnWarn,
|
||||||
compatConfig
|
compatConfig,
|
||||||
}: TransformOptions
|
}: TransformOptions,
|
||||||
): TransformContext {
|
): TransformContext {
|
||||||
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
|
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
|
||||||
const context: TransformContext = {
|
const context: TransformContext = {
|
||||||
|
@ -190,7 +190,7 @@ export function createTransformContext(
|
||||||
vFor: 0,
|
vFor: 0,
|
||||||
vSlot: 0,
|
vSlot: 0,
|
||||||
vPre: 0,
|
vPre: 0,
|
||||||
vOnce: 0
|
vOnce: 0,
|
||||||
},
|
},
|
||||||
parent: null,
|
parent: null,
|
||||||
currentNode: root,
|
currentNode: root,
|
||||||
|
@ -287,14 +287,14 @@ export function createTransformContext(
|
||||||
`_hoisted_${context.hoists.length}`,
|
`_hoisted_${context.hoists.length}`,
|
||||||
false,
|
false,
|
||||||
exp.loc,
|
exp.loc,
|
||||||
ConstantTypes.CAN_HOIST
|
ConstantTypes.CAN_HOIST,
|
||||||
)
|
)
|
||||||
identifier.hoisted = exp
|
identifier.hoisted = exp
|
||||||
return identifier
|
return identifier
|
||||||
},
|
},
|
||||||
cache(exp, isVNode = false) {
|
cache(exp, isVNode = false) {
|
||||||
return createCacheExpression(context.cached++, exp, isVNode)
|
return createCacheExpression(context.cached++, exp, isVNode)
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
|
@ -383,7 +383,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
|
||||||
undefined,
|
undefined,
|
||||||
true,
|
true,
|
||||||
undefined,
|
undefined,
|
||||||
false /* isComponent */
|
false /* isComponent */,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// no children = noop. codegen will return null.
|
// no children = noop. codegen will return null.
|
||||||
|
@ -392,7 +392,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
|
||||||
|
|
||||||
export function traverseChildren(
|
export function traverseChildren(
|
||||||
parent: ParentNode,
|
parent: ParentNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
) {
|
) {
|
||||||
let i = 0
|
let i = 0
|
||||||
const nodeRemoved = () => {
|
const nodeRemoved = () => {
|
||||||
|
@ -410,7 +410,7 @@ export function traverseChildren(
|
||||||
|
|
||||||
export function traverseNode(
|
export function traverseNode(
|
||||||
node: RootNode | TemplateChildNode,
|
node: RootNode | TemplateChildNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
) {
|
) {
|
||||||
context.currentNode = node
|
context.currentNode = node
|
||||||
// apply transform plugins
|
// apply transform plugins
|
||||||
|
@ -473,7 +473,7 @@ export function traverseNode(
|
||||||
|
|
||||||
export function createStructuralDirectiveTransform(
|
export function createStructuralDirectiveTransform(
|
||||||
name: string | RegExp,
|
name: string | RegExp,
|
||||||
fn: StructuralDirectiveTransform
|
fn: StructuralDirectiveTransform,
|
||||||
): NodeTransform {
|
): NodeTransform {
|
||||||
const matches = isString(name)
|
const matches = isString(name)
|
||||||
? (n: string) => n === name
|
? (n: string) => n === name
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
import {
|
import {
|
||||||
|
type CallExpression,
|
||||||
|
type ComponentNode,
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
RootNode,
|
|
||||||
NodeTypes,
|
|
||||||
TemplateChildNode,
|
|
||||||
SimpleExpressionNode,
|
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
PlainElementNode,
|
type JSChildNode,
|
||||||
ComponentNode,
|
NodeTypes,
|
||||||
TemplateNode,
|
type ParentNode,
|
||||||
VNodeCall,
|
type PlainElementNode,
|
||||||
ParentNode,
|
type RootNode,
|
||||||
JSChildNode,
|
type SimpleExpressionNode,
|
||||||
CallExpression,
|
type TemplateChildNode,
|
||||||
|
type TemplateNode,
|
||||||
|
type VNodeCall,
|
||||||
createArrayExpression,
|
createArrayExpression,
|
||||||
getVNodeBlockHelper,
|
getVNodeBlockHelper,
|
||||||
getVNodeHelper
|
getVNodeHelper,
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { TransformContext } from '../transform'
|
import type { TransformContext } from '../transform'
|
||||||
import { PatchFlags, isString, isSymbol, isArray } from '@vue/shared'
|
import { PatchFlags, isArray, isString, isSymbol } from '@vue/shared'
|
||||||
import { isSlotOutlet } from '../utils'
|
import { isSlotOutlet } from '../utils'
|
||||||
import {
|
import {
|
||||||
OPEN_BLOCK,
|
|
||||||
GUARD_REACTIVE_PROPS,
|
GUARD_REACTIVE_PROPS,
|
||||||
NORMALIZE_CLASS,
|
NORMALIZE_CLASS,
|
||||||
NORMALIZE_PROPS,
|
NORMALIZE_PROPS,
|
||||||
NORMALIZE_STYLE
|
NORMALIZE_STYLE,
|
||||||
|
OPEN_BLOCK,
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
|
|
||||||
export function hoistStatic(root: RootNode, context: TransformContext) {
|
export function hoistStatic(root: RootNode, context: TransformContext) {
|
||||||
|
@ -33,13 +33,13 @@ export function hoistStatic(root: RootNode, context: TransformContext) {
|
||||||
context,
|
context,
|
||||||
// Root node is unfortunately non-hoistable due to potential parent
|
// Root node is unfortunately non-hoistable due to potential parent
|
||||||
// fallthrough attributes.
|
// fallthrough attributes.
|
||||||
isSingleElementRoot(root, root.children[0])
|
isSingleElementRoot(root, root.children[0]),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSingleElementRoot(
|
export function isSingleElementRoot(
|
||||||
root: RootNode,
|
root: RootNode,
|
||||||
child: TemplateChildNode
|
child: TemplateChildNode,
|
||||||
): child is PlainElementNode | ComponentNode | TemplateNode {
|
): child is PlainElementNode | ComponentNode | TemplateNode {
|
||||||
const { children } = root
|
const { children } = root
|
||||||
return (
|
return (
|
||||||
|
@ -52,7 +52,7 @@ export function isSingleElementRoot(
|
||||||
function walk(
|
function walk(
|
||||||
node: ParentNode,
|
node: ParentNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
doNotHoistNode: boolean = false
|
doNotHoistNode: boolean = false,
|
||||||
) {
|
) {
|
||||||
const { children } = node
|
const { children } = node
|
||||||
const originalCount = children.length
|
const originalCount = children.length
|
||||||
|
@ -120,7 +120,7 @@ function walk(
|
||||||
walk(
|
walk(
|
||||||
child.branches[i],
|
child.branches[i],
|
||||||
context,
|
context,
|
||||||
child.branches[i].children.length === 1
|
child.branches[i].children.length === 1,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,7 @@ function walk(
|
||||||
isArray(node.codegenNode.children)
|
isArray(node.codegenNode.children)
|
||||||
) {
|
) {
|
||||||
const hoisted = context.hoist(
|
const hoisted = context.hoist(
|
||||||
createArrayExpression(node.codegenNode.children)
|
createArrayExpression(node.codegenNode.children),
|
||||||
)
|
)
|
||||||
// #6978, #7138, #7114
|
// #6978, #7138, #7114
|
||||||
// a hoisted children array inside v-for can caused HMR errors since
|
// a hoisted children array inside v-for can caused HMR errors since
|
||||||
|
@ -155,7 +155,7 @@ function walk(
|
||||||
|
|
||||||
export function getConstantType(
|
export function getConstantType(
|
||||||
node: TemplateChildNode | SimpleExpressionNode,
|
node: TemplateChildNode | SimpleExpressionNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): ConstantTypes {
|
): ConstantTypes {
|
||||||
const { constantCache } = context
|
const { constantCache } = context
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
|
@ -244,7 +244,7 @@ export function getConstantType(
|
||||||
|
|
||||||
context.removeHelper(OPEN_BLOCK)
|
context.removeHelper(OPEN_BLOCK)
|
||||||
context.removeHelper(
|
context.removeHelper(
|
||||||
getVNodeBlockHelper(context.inSSR, codegenNode.isComponent)
|
getVNodeBlockHelper(context.inSSR, codegenNode.isComponent),
|
||||||
)
|
)
|
||||||
codegenNode.isBlock = false
|
codegenNode.isBlock = false
|
||||||
context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent))
|
context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent))
|
||||||
|
@ -296,12 +296,12 @@ const allowHoistedHelperSet = new Set([
|
||||||
NORMALIZE_CLASS,
|
NORMALIZE_CLASS,
|
||||||
NORMALIZE_STYLE,
|
NORMALIZE_STYLE,
|
||||||
NORMALIZE_PROPS,
|
NORMALIZE_PROPS,
|
||||||
GUARD_REACTIVE_PROPS
|
GUARD_REACTIVE_PROPS,
|
||||||
])
|
])
|
||||||
|
|
||||||
function getConstantTypeOfHelperCall(
|
function getConstantTypeOfHelperCall(
|
||||||
value: CallExpression,
|
value: CallExpression,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): ConstantTypes {
|
): ConstantTypes {
|
||||||
if (
|
if (
|
||||||
value.type === NodeTypes.JS_CALL_EXPRESSION &&
|
value.type === NodeTypes.JS_CALL_EXPRESSION &&
|
||||||
|
@ -321,7 +321,7 @@ function getConstantTypeOfHelperCall(
|
||||||
|
|
||||||
function getGeneratedPropsConstantType(
|
function getGeneratedPropsConstantType(
|
||||||
node: PlainElementNode,
|
node: PlainElementNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): ConstantTypes {
|
): ConstantTypes {
|
||||||
let returnType = ConstantTypes.CAN_STRINGIFY
|
let returnType = ConstantTypes.CAN_STRINGIFY
|
||||||
const props = getNodeProps(node)
|
const props = getNodeProps(node)
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
import { DirectiveTransform } from '../transform'
|
import type { DirectiveTransform } from '../transform'
|
||||||
|
|
||||||
export const noopDirectiveTransform: DirectiveTransform = () => ({ props: [] })
|
export const noopDirectiveTransform: DirectiveTransform = () => ({ props: [] })
|
||||||
|
|
|
@ -1,68 +1,68 @@
|
||||||
import { NodeTransform, TransformContext } from '../transform'
|
import type { NodeTransform, TransformContext } from '../transform'
|
||||||
import {
|
import {
|
||||||
NodeTypes,
|
type ArrayExpression,
|
||||||
|
type CallExpression,
|
||||||
|
type ComponentNode,
|
||||||
|
ConstantTypes,
|
||||||
|
type DirectiveArguments,
|
||||||
|
type DirectiveNode,
|
||||||
|
type ElementNode,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
CallExpression,
|
type ExpressionNode,
|
||||||
ObjectExpression,
|
type JSChildNode,
|
||||||
ElementNode,
|
NodeTypes,
|
||||||
DirectiveNode,
|
type ObjectExpression,
|
||||||
ExpressionNode,
|
type Property,
|
||||||
ArrayExpression,
|
type TemplateTextChildNode,
|
||||||
createCallExpression,
|
type VNodeCall,
|
||||||
createArrayExpression,
|
createArrayExpression,
|
||||||
|
createCallExpression,
|
||||||
|
createObjectExpression,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
createObjectExpression,
|
|
||||||
Property,
|
|
||||||
ComponentNode,
|
|
||||||
VNodeCall,
|
|
||||||
TemplateTextChildNode,
|
|
||||||
DirectiveArguments,
|
|
||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
ConstantTypes,
|
|
||||||
JSChildNode
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import {
|
import {
|
||||||
PatchFlags,
|
|
||||||
PatchFlagNames,
|
PatchFlagNames,
|
||||||
isSymbol,
|
PatchFlags,
|
||||||
isOn,
|
|
||||||
isObject,
|
|
||||||
isReservedProp,
|
|
||||||
capitalize,
|
|
||||||
camelize,
|
camelize,
|
||||||
isBuiltInDirective
|
capitalize,
|
||||||
|
isBuiltInDirective,
|
||||||
|
isObject,
|
||||||
|
isOn,
|
||||||
|
isReservedProp,
|
||||||
|
isSymbol,
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import {
|
import {
|
||||||
RESOLVE_DIRECTIVE,
|
GUARD_REACTIVE_PROPS,
|
||||||
RESOLVE_COMPONENT,
|
KEEP_ALIVE,
|
||||||
RESOLVE_DYNAMIC_COMPONENT,
|
|
||||||
MERGE_PROPS,
|
MERGE_PROPS,
|
||||||
NORMALIZE_CLASS,
|
NORMALIZE_CLASS,
|
||||||
NORMALIZE_STYLE,
|
|
||||||
NORMALIZE_PROPS,
|
NORMALIZE_PROPS,
|
||||||
TO_HANDLERS,
|
NORMALIZE_STYLE,
|
||||||
TELEPORT,
|
RESOLVE_COMPONENT,
|
||||||
KEEP_ALIVE,
|
RESOLVE_DIRECTIVE,
|
||||||
|
RESOLVE_DYNAMIC_COMPONENT,
|
||||||
SUSPENSE,
|
SUSPENSE,
|
||||||
|
TELEPORT,
|
||||||
|
TO_HANDLERS,
|
||||||
UNREF,
|
UNREF,
|
||||||
GUARD_REACTIVE_PROPS
|
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
import {
|
import {
|
||||||
toValidAssetId,
|
|
||||||
findProp,
|
findProp,
|
||||||
isCoreComponent,
|
isCoreComponent,
|
||||||
isStaticArgOf,
|
isStaticArgOf,
|
||||||
isStaticExp
|
isStaticExp,
|
||||||
|
toValidAssetId,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { buildSlots } from './vSlot'
|
import { buildSlots } from './vSlot'
|
||||||
import { getConstantType } from './hoistStatic'
|
import { getConstantType } from './hoistStatic'
|
||||||
import { BindingTypes } from '../options'
|
import { BindingTypes } from '../options'
|
||||||
import {
|
import {
|
||||||
checkCompatEnabled,
|
|
||||||
CompilerDeprecationTypes,
|
CompilerDeprecationTypes,
|
||||||
isCompatEnabled
|
checkCompatEnabled,
|
||||||
|
isCompatEnabled,
|
||||||
} from '../compat/compatConfig'
|
} from '../compat/compatConfig'
|
||||||
|
|
||||||
// some directive transforms (e.g. v-model) may return a symbol for runtime
|
// some directive transforms (e.g. v-model) may return a symbol for runtime
|
||||||
|
@ -125,7 +125,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||||
context,
|
context,
|
||||||
undefined,
|
undefined,
|
||||||
isComponent,
|
isComponent,
|
||||||
isDynamicComponent
|
isDynamicComponent,
|
||||||
)
|
)
|
||||||
vnodeProps = propsBuildResult.props
|
vnodeProps = propsBuildResult.props
|
||||||
patchFlag = propsBuildResult.patchFlag
|
patchFlag = propsBuildResult.patchFlag
|
||||||
|
@ -134,7 +134,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||||
vnodeDirectives =
|
vnodeDirectives =
|
||||||
directives && directives.length
|
directives && directives.length
|
||||||
? (createArrayExpression(
|
? (createArrayExpression(
|
||||||
directives.map(dir => buildDirectiveArgs(dir, context))
|
directives.map(dir => buildDirectiveArgs(dir, context)),
|
||||||
) as DirectiveArguments)
|
) as DirectiveArguments)
|
||||||
: undefined
|
: undefined
|
||||||
|
|
||||||
|
@ -160,8 +160,8 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||||
createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, {
|
createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, {
|
||||||
start: node.children[0].loc.start,
|
start: node.children[0].loc.start,
|
||||||
end: node.children[node.children.length - 1].loc.end,
|
end: node.children[node.children.length - 1].loc.end,
|
||||||
source: ''
|
source: '',
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||||
!!shouldUseBlock,
|
!!shouldUseBlock,
|
||||||
false /* disableTracking */,
|
false /* disableTracking */,
|
||||||
isComponent,
|
isComponent,
|
||||||
node.loc
|
node.loc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +247,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
||||||
export function resolveComponentType(
|
export function resolveComponentType(
|
||||||
node: ComponentNode,
|
node: ComponentNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
ssr = false
|
ssr = false,
|
||||||
) {
|
) {
|
||||||
let { tag } = node
|
let { tag } = node
|
||||||
|
|
||||||
|
@ -260,7 +260,7 @@ export function resolveComponentType(
|
||||||
(__COMPAT__ &&
|
(__COMPAT__ &&
|
||||||
isCompatEnabled(
|
isCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||||
context
|
context,
|
||||||
))
|
))
|
||||||
) {
|
) {
|
||||||
const exp =
|
const exp =
|
||||||
|
@ -269,7 +269,7 @@ export function resolveComponentType(
|
||||||
: isProp.exp
|
: isProp.exp
|
||||||
if (exp) {
|
if (exp) {
|
||||||
return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
|
return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
|
||||||
exp
|
exp,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -388,7 +388,7 @@ export function buildProps(
|
||||||
props: ElementNode['props'] = node.props,
|
props: ElementNode['props'] = node.props,
|
||||||
isComponent: boolean,
|
isComponent: boolean,
|
||||||
isDynamicComponent: boolean,
|
isDynamicComponent: boolean,
|
||||||
ssr = false
|
ssr = false,
|
||||||
): {
|
): {
|
||||||
props: PropsExpression | undefined
|
props: PropsExpression | undefined
|
||||||
directives: DirectiveNode[]
|
directives: DirectiveNode[]
|
||||||
|
@ -416,7 +416,7 @@ export function buildProps(
|
||||||
const pushMergeArg = (arg?: PropsExpression) => {
|
const pushMergeArg = (arg?: PropsExpression) => {
|
||||||
if (properties.length) {
|
if (properties.length) {
|
||||||
mergeArgs.push(
|
mergeArgs.push(
|
||||||
createObjectExpression(dedupeProperties(properties), elementLoc)
|
createObjectExpression(dedupeProperties(properties), elementLoc),
|
||||||
)
|
)
|
||||||
properties = []
|
properties = []
|
||||||
}
|
}
|
||||||
|
@ -496,8 +496,8 @@ export function buildProps(
|
||||||
properties.push(
|
properties.push(
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression('ref_for', true),
|
createSimpleExpression('ref_for', true),
|
||||||
createSimpleExpression('true')
|
createSimpleExpression('true'),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// in inline mode there is no setupState object, so we can't use string
|
// in inline mode there is no setupState object, so we can't use string
|
||||||
|
@ -514,8 +514,8 @@ export function buildProps(
|
||||||
properties.push(
|
properties.push(
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression('ref_key', true),
|
createSimpleExpression('ref_key', true),
|
||||||
createSimpleExpression(value.content, true, value.loc)
|
createSimpleExpression(value.content, true, value.loc),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -528,7 +528,7 @@ export function buildProps(
|
||||||
(__COMPAT__ &&
|
(__COMPAT__ &&
|
||||||
isCompatEnabled(
|
isCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||||
context
|
context,
|
||||||
)))
|
)))
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
|
@ -539,9 +539,9 @@ export function buildProps(
|
||||||
createSimpleExpression(
|
createSimpleExpression(
|
||||||
value ? value.content : '',
|
value ? value.content : '',
|
||||||
isStatic,
|
isStatic,
|
||||||
value ? value.loc : loc
|
value ? value.loc : loc,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// directives
|
// directives
|
||||||
|
@ -553,7 +553,7 @@ export function buildProps(
|
||||||
if (name === 'slot') {
|
if (name === 'slot') {
|
||||||
if (!isComponent) {
|
if (!isComponent) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, loc)
|
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -571,7 +571,7 @@ export function buildProps(
|
||||||
(__COMPAT__ &&
|
(__COMPAT__ &&
|
||||||
isCompatEnabled(
|
isCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||||
context
|
context,
|
||||||
))))
|
))))
|
||||||
) {
|
) {
|
||||||
continue
|
continue
|
||||||
|
@ -595,8 +595,8 @@ export function buildProps(
|
||||||
properties.push(
|
properties.push(
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression('ref_for', true),
|
createSimpleExpression('ref_for', true),
|
||||||
createSimpleExpression('true')
|
createSimpleExpression('true'),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -634,7 +634,7 @@ export function buildProps(
|
||||||
checkCompatEnabled(
|
checkCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,
|
CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,
|
||||||
context,
|
context,
|
||||||
loc
|
loc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -642,7 +642,7 @@ export function buildProps(
|
||||||
if (
|
if (
|
||||||
isCompatEnabled(
|
isCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,
|
CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
mergeArgs.unshift(exp)
|
mergeArgs.unshift(exp)
|
||||||
|
@ -657,7 +657,7 @@ export function buildProps(
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
loc,
|
loc,
|
||||||
callee: context.helper(TO_HANDLERS),
|
callee: context.helper(TO_HANDLERS),
|
||||||
arguments: isComponent ? [exp] : [exp, `true`]
|
arguments: isComponent ? [exp] : [exp, `true`],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -666,8 +666,8 @@ export function buildProps(
|
||||||
isVBind
|
isVBind
|
||||||
? ErrorCodes.X_V_BIND_NO_EXPRESSION
|
? ErrorCodes.X_V_BIND_NO_EXPRESSION
|
||||||
: ErrorCodes.X_V_ON_NO_EXPRESSION,
|
: ErrorCodes.X_V_ON_NO_EXPRESSION,
|
||||||
loc
|
loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
|
@ -716,7 +716,7 @@ export function buildProps(
|
||||||
propsExpression = createCallExpression(
|
propsExpression = createCallExpression(
|
||||||
context.helper(MERGE_PROPS),
|
context.helper(MERGE_PROPS),
|
||||||
mergeArgs,
|
mergeArgs,
|
||||||
elementLoc
|
elementLoc,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// single v-bind with nothing else - no need for a mergeProps call
|
// single v-bind with nothing else - no need for a mergeProps call
|
||||||
|
@ -725,7 +725,7 @@ export function buildProps(
|
||||||
} else if (properties.length) {
|
} else if (properties.length) {
|
||||||
propsExpression = createObjectExpression(
|
propsExpression = createObjectExpression(
|
||||||
dedupeProperties(properties),
|
dedupeProperties(properties),
|
||||||
elementLoc
|
elementLoc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -785,7 +785,7 @@ export function buildProps(
|
||||||
if (classProp && !isStaticExp(classProp.value)) {
|
if (classProp && !isStaticExp(classProp.value)) {
|
||||||
classProp.value = createCallExpression(
|
classProp.value = createCallExpression(
|
||||||
context.helper(NORMALIZE_CLASS),
|
context.helper(NORMALIZE_CLASS),
|
||||||
[classProp.value]
|
[classProp.value],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
|
@ -801,14 +801,14 @@ export function buildProps(
|
||||||
) {
|
) {
|
||||||
styleProp.value = createCallExpression(
|
styleProp.value = createCallExpression(
|
||||||
context.helper(NORMALIZE_STYLE),
|
context.helper(NORMALIZE_STYLE),
|
||||||
[styleProp.value]
|
[styleProp.value],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// dynamic key binding, wrap with `normalizeProps`
|
// dynamic key binding, wrap with `normalizeProps`
|
||||||
propsExpression = createCallExpression(
|
propsExpression = createCallExpression(
|
||||||
context.helper(NORMALIZE_PROPS),
|
context.helper(NORMALIZE_PROPS),
|
||||||
[propsExpression]
|
[propsExpression],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -821,9 +821,9 @@ export function buildProps(
|
||||||
context.helper(NORMALIZE_PROPS),
|
context.helper(NORMALIZE_PROPS),
|
||||||
[
|
[
|
||||||
createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [
|
createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [
|
||||||
propsExpression
|
propsExpression,
|
||||||
])
|
]),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -834,7 +834,7 @@ export function buildProps(
|
||||||
directives: runtimeDirectives,
|
directives: runtimeDirectives,
|
||||||
patchFlag,
|
patchFlag,
|
||||||
dynamicPropNames,
|
dynamicPropNames,
|
||||||
shouldUseBlock
|
shouldUseBlock,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -875,14 +875,14 @@ function mergeAsArray(existing: Property, incoming: Property) {
|
||||||
} else {
|
} else {
|
||||||
existing.value = createArrayExpression(
|
existing.value = createArrayExpression(
|
||||||
[existing.value, incoming.value],
|
[existing.value, incoming.value],
|
||||||
existing.loc
|
existing.loc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function buildDirectiveArgs(
|
export function buildDirectiveArgs(
|
||||||
dir: DirectiveNode,
|
dir: DirectiveNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): ArrayExpression {
|
): ArrayExpression {
|
||||||
const dirArgs: ArrayExpression['elements'] = []
|
const dirArgs: ArrayExpression['elements'] = []
|
||||||
const runtime = directiveImportMap.get(dir)
|
const runtime = directiveImportMap.get(dir)
|
||||||
|
@ -922,10 +922,10 @@ export function buildDirectiveArgs(
|
||||||
dirArgs.push(
|
dirArgs.push(
|
||||||
createObjectExpression(
|
createObjectExpression(
|
||||||
dir.modifiers.map(modifier =>
|
dir.modifiers.map(modifier =>
|
||||||
createObjectProperty(modifier, trueExpression)
|
createObjectProperty(modifier, trueExpression),
|
||||||
|
),
|
||||||
|
loc,
|
||||||
),
|
),
|
||||||
loc
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return createArrayExpression(dirArgs, dir.loc)
|
return createArrayExpression(dirArgs, dir.loc)
|
||||||
|
|
|
@ -7,36 +7,36 @@
|
||||||
// - This transform is only applied in non-browser builds because it relies on
|
// - This transform is only applied in non-browser builds because it relies on
|
||||||
// an additional JavaScript parser. In the browser, there is no source-map
|
// an additional JavaScript parser. In the browser, there is no source-map
|
||||||
// support and the code is wrapped in `with (this) { ... }`.
|
// support and the code is wrapped in `with (this) { ... }`.
|
||||||
import { NodeTransform, TransformContext } from '../transform'
|
import type { NodeTransform, TransformContext } from '../transform'
|
||||||
import {
|
import {
|
||||||
|
type CompoundExpressionNode,
|
||||||
|
ConstantTypes,
|
||||||
|
type ExpressionNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
createSimpleExpression,
|
type SimpleExpressionNode,
|
||||||
ExpressionNode,
|
|
||||||
SimpleExpressionNode,
|
|
||||||
CompoundExpressionNode,
|
|
||||||
createCompoundExpression,
|
createCompoundExpression,
|
||||||
ConstantTypes
|
createSimpleExpression,
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import {
|
import {
|
||||||
isInDestructureAssignment,
|
isInDestructureAssignment,
|
||||||
isStaticProperty,
|
isStaticProperty,
|
||||||
isStaticPropertyKey,
|
isStaticPropertyKey,
|
||||||
walkIdentifiers
|
walkIdentifiers,
|
||||||
} from '../babelUtils'
|
} from '../babelUtils'
|
||||||
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
|
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
|
||||||
import {
|
import {
|
||||||
isGloballyAllowed,
|
genPropsAccessExp,
|
||||||
makeMap,
|
|
||||||
hasOwn,
|
hasOwn,
|
||||||
|
isGloballyAllowed,
|
||||||
isString,
|
isString,
|
||||||
genPropsAccessExp
|
makeMap,
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import {
|
import type {
|
||||||
Node,
|
|
||||||
Identifier,
|
|
||||||
AssignmentExpression,
|
AssignmentExpression,
|
||||||
UpdateExpression
|
Identifier,
|
||||||
|
Node,
|
||||||
|
UpdateExpression,
|
||||||
} from '@babel/types'
|
} from '@babel/types'
|
||||||
import { validateBrowserExpression } from '../validateExpression'
|
import { validateBrowserExpression } from '../validateExpression'
|
||||||
import { parse } from '@babel/parser'
|
import { parse } from '@babel/parser'
|
||||||
|
@ -53,7 +53,7 @@ export const transformExpression: NodeTransform = (node, context) => {
|
||||||
if (node.type === NodeTypes.INTERPOLATION) {
|
if (node.type === NodeTypes.INTERPOLATION) {
|
||||||
node.content = processExpression(
|
node.content = processExpression(
|
||||||
node.content as SimpleExpressionNode,
|
node.content as SimpleExpressionNode,
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
} else if (node.type === NodeTypes.ELEMENT) {
|
} else if (node.type === NodeTypes.ELEMENT) {
|
||||||
// handle directives on element
|
// handle directives on element
|
||||||
|
@ -74,7 +74,7 @@ export const transformExpression: NodeTransform = (node, context) => {
|
||||||
exp,
|
exp,
|
||||||
context,
|
context,
|
||||||
// slot args must be processed as function params
|
// slot args must be processed as function params
|
||||||
dir.name === 'slot'
|
dir.name === 'slot',
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) {
|
if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) {
|
||||||
|
@ -104,7 +104,7 @@ export function processExpression(
|
||||||
asParams = false,
|
asParams = false,
|
||||||
// v-on handler values may contain multiple statements
|
// v-on handler values may contain multiple statements
|
||||||
asRawStatements = false,
|
asRawStatements = false,
|
||||||
localVars: Record<string, number> = Object.create(context.identifiers)
|
localVars: Record<string, number> = Object.create(context.identifiers),
|
||||||
): ExpressionNode {
|
): ExpressionNode {
|
||||||
if (__BROWSER__) {
|
if (__BROWSER__) {
|
||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
|
@ -163,8 +163,8 @@ export function processExpression(
|
||||||
context,
|
context,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
knownIds
|
knownIds,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
return `${context.helperString(IS_REF)}(${raw})${
|
return `${context.helperString(IS_REF)}(${raw})${
|
||||||
context.isTS ? ` //@ts-ignore\n` : ``
|
context.isTS ? ` //@ts-ignore\n` : ``
|
||||||
|
@ -267,7 +267,7 @@ export function processExpression(
|
||||||
: `(${rawExp})${asParams ? `=>{}` : ``}`
|
: `(${rawExp})${asParams ? `=>{}` : ``}`
|
||||||
try {
|
try {
|
||||||
ast = parse(source, {
|
ast = parse(source, {
|
||||||
plugins: context.expressionPlugins
|
plugins: context.expressionPlugins,
|
||||||
}).program
|
}).program
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
context.onError(
|
context.onError(
|
||||||
|
@ -275,8 +275,8 @@ export function processExpression(
|
||||||
ErrorCodes.X_INVALID_EXPRESSION,
|
ErrorCodes.X_INVALID_EXPRESSION,
|
||||||
node.loc,
|
node.loc,
|
||||||
undefined,
|
undefined,
|
||||||
e.message
|
e.message,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ export function processExpression(
|
||||||
},
|
},
|
||||||
true, // invoke on ALL identifiers
|
true, // invoke on ALL identifiers
|
||||||
parentStack,
|
parentStack,
|
||||||
knownIds
|
knownIds,
|
||||||
)
|
)
|
||||||
|
|
||||||
// We break up the compound expression into an array of strings and sub
|
// We break up the compound expression into an array of strings and sub
|
||||||
|
@ -346,10 +346,12 @@ export function processExpression(
|
||||||
{
|
{
|
||||||
start: advancePositionWithClone(node.loc.start, source, start),
|
start: advancePositionWithClone(node.loc.start, source, start),
|
||||||
end: advancePositionWithClone(node.loc.start, source, end),
|
end: advancePositionWithClone(node.loc.start, source, end),
|
||||||
source
|
source,
|
||||||
},
|
},
|
||||||
id.isConstant ? ConstantTypes.CAN_STRINGIFY : ConstantTypes.NOT_CONSTANT
|
id.isConstant
|
||||||
)
|
? ConstantTypes.CAN_STRINGIFY
|
||||||
|
: ConstantTypes.NOT_CONSTANT,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
if (i === ids.length - 1 && end < rawExp.length) {
|
if (i === ids.length - 1 && end < rawExp.length) {
|
||||||
children.push(rawExp.slice(end))
|
children.push(rawExp.slice(end))
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { NodeTransform, TransformContext } from '../transform'
|
import type { NodeTransform, TransformContext } from '../transform'
|
||||||
import {
|
import {
|
||||||
|
type CallExpression,
|
||||||
|
type ExpressionNode,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
CallExpression,
|
type SlotOutletNode,
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
ExpressionNode,
|
createFunctionExpression,
|
||||||
SlotOutletNode,
|
|
||||||
createFunctionExpression
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { isSlotOutlet, isStaticArgOf, isStaticExp } from '../utils'
|
import { isSlotOutlet, isStaticArgOf, isStaticExp } from '../utils'
|
||||||
import { buildProps, PropsExpression } from './transformElement'
|
import { type PropsExpression, buildProps } from './transformElement'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import { RENDER_SLOT } from '../runtimeHelpers'
|
import { RENDER_SLOT } from '../runtimeHelpers'
|
||||||
import { camelize } from '@vue/shared'
|
import { camelize } from '@vue/shared'
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||||
slotName,
|
slotName,
|
||||||
'{}',
|
'{}',
|
||||||
'undefined',
|
'undefined',
|
||||||
'true'
|
'true',
|
||||||
]
|
]
|
||||||
let expectedLen = 2
|
let expectedLen = 2
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
||||||
node.codegenNode = createCallExpression(
|
node.codegenNode = createCallExpression(
|
||||||
context.helper(RENDER_SLOT),
|
context.helper(RENDER_SLOT),
|
||||||
slotArgs,
|
slotArgs,
|
||||||
loc
|
loc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ interface SlotOutletProcessResult {
|
||||||
|
|
||||||
export function processSlotOutlet(
|
export function processSlotOutlet(
|
||||||
node: SlotOutletNode,
|
node: SlotOutletNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): SlotOutletProcessResult {
|
): SlotOutletProcessResult {
|
||||||
let slotName: string | ExpressionNode = `"default"`
|
let slotName: string | ExpressionNode = `"default"`
|
||||||
let slotProps: PropsExpression | undefined = undefined
|
let slotProps: PropsExpression | undefined = undefined
|
||||||
|
@ -92,7 +92,7 @@ export function processSlotOutlet(
|
||||||
context,
|
context,
|
||||||
nonNameProps,
|
nonNameProps,
|
||||||
false,
|
false,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
slotProps = props
|
slotProps = props
|
||||||
|
|
||||||
|
@ -100,14 +100,14 @@ export function processSlotOutlet(
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(
|
createCompilerError(
|
||||||
ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
|
ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
|
||||||
directives[0].loc
|
directives[0].loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
slotName,
|
slotName,
|
||||||
slotProps
|
slotProps,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { NodeTransform } from '../transform'
|
import type { NodeTransform } from '../transform'
|
||||||
import {
|
import {
|
||||||
NodeTypes,
|
type CallExpression,
|
||||||
CompoundExpressionNode,
|
type CompoundExpressionNode,
|
||||||
createCallExpression,
|
|
||||||
CallExpression,
|
|
||||||
ElementTypes,
|
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
createCompoundExpression
|
ElementTypes,
|
||||||
|
NodeTypes,
|
||||||
|
createCallExpression,
|
||||||
|
createCompoundExpression,
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { isText } from '../utils'
|
import { isText } from '../utils'
|
||||||
import { CREATE_TEXT } from '../runtimeHelpers'
|
import { CREATE_TEXT } from '../runtimeHelpers'
|
||||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
import { PatchFlagNames, PatchFlags } from '@vue/shared'
|
||||||
import { getConstantType } from './hoistStatic'
|
import { getConstantType } from './hoistStatic'
|
||||||
|
|
||||||
// Merge adjacent text nodes and expressions into a single expression
|
// Merge adjacent text nodes and expressions into a single expression
|
||||||
|
@ -39,7 +39,7 @@ export const transformText: NodeTransform = (node, context) => {
|
||||||
if (!currentContainer) {
|
if (!currentContainer) {
|
||||||
currentContainer = children[i] = createCompoundExpression(
|
currentContainer = children[i] = createCompoundExpression(
|
||||||
[child],
|
[child],
|
||||||
child.loc
|
child.loc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// merge adjacent text node into current
|
// merge adjacent text node into current
|
||||||
|
@ -72,7 +72,7 @@ export const transformText: NodeTransform = (node, context) => {
|
||||||
!node.props.find(
|
!node.props.find(
|
||||||
p =>
|
p =>
|
||||||
p.type === NodeTypes.DIRECTIVE &&
|
p.type === NodeTypes.DIRECTIVE &&
|
||||||
!context.directiveTransforms[p.name]
|
!context.directiveTransforms[p.name],
|
||||||
) &&
|
) &&
|
||||||
// in compat mode, <template> tags with no special directives
|
// in compat mode, <template> tags with no special directives
|
||||||
// will be rendered as a fragment so its children must be
|
// will be rendered as a fragment so its children must be
|
||||||
|
@ -100,7 +100,7 @@ export const transformText: NodeTransform = (node, context) => {
|
||||||
) {
|
) {
|
||||||
callArgs.push(
|
callArgs.push(
|
||||||
PatchFlags.TEXT +
|
PatchFlags.TEXT +
|
||||||
(__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.TEXT]} */` : ``)
|
(__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.TEXT]} */` : ``),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
children[i] = {
|
children[i] = {
|
||||||
|
@ -109,8 +109,8 @@ export const transformText: NodeTransform = (node, context) => {
|
||||||
loc: child.loc,
|
loc: child.loc,
|
||||||
codegenNode: createCallExpression(
|
codegenNode: createCallExpression(
|
||||||
context.helper(CREATE_TEXT),
|
context.helper(CREATE_TEXT),
|
||||||
callArgs
|
callArgs,
|
||||||
)
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import { DirectiveTransform } from '../transform'
|
import type { DirectiveTransform } from '../transform'
|
||||||
import {
|
import {
|
||||||
|
type ExpressionNode,
|
||||||
|
NodeTypes,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
ExpressionNode,
|
|
||||||
NodeTypes
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import { camelize } from '@vue/shared'
|
import { camelize } from '@vue/shared'
|
||||||
import { CAMELIZE } from '../runtimeHelpers'
|
import { CAMELIZE } from '../runtimeHelpers'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
|
@ -63,12 +63,12 @@ export const transformBind: DirectiveTransform = (dir, _node, context) => {
|
||||||
) {
|
) {
|
||||||
context.onError(createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc))
|
context.onError(createCompilerError(ErrorCodes.X_V_BIND_NO_EXPRESSION, loc))
|
||||||
return {
|
return {
|
||||||
props: [createObjectProperty(arg, createSimpleExpression('', true, loc))]
|
props: [createObjectProperty(arg, createSimpleExpression('', true, loc))],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: [createObjectProperty(arg, exp)]
|
props: [createObjectProperty(arg, exp)],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,52 +1,52 @@
|
||||||
import {
|
import {
|
||||||
|
type TransformContext,
|
||||||
createStructuralDirectiveTransform,
|
createStructuralDirectiveTransform,
|
||||||
TransformContext
|
|
||||||
} from '../transform'
|
} from '../transform'
|
||||||
import {
|
import {
|
||||||
|
type BlockCodegenNode,
|
||||||
|
ConstantTypes,
|
||||||
|
type DirectiveNode,
|
||||||
|
type ElementNode,
|
||||||
|
type ExpressionNode,
|
||||||
|
type ForCodegenNode,
|
||||||
|
type ForIteratorExpression,
|
||||||
|
type ForNode,
|
||||||
|
type ForParseResult,
|
||||||
|
type ForRenderListExpression,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
ExpressionNode,
|
type PlainElementNode,
|
||||||
createSimpleExpression,
|
type RenderSlotCall,
|
||||||
SimpleExpressionNode,
|
type SimpleExpressionNode,
|
||||||
|
type SlotOutletNode,
|
||||||
|
type VNodeCall,
|
||||||
|
createBlockStatement,
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
|
createCompoundExpression,
|
||||||
createFunctionExpression,
|
createFunctionExpression,
|
||||||
createObjectExpression,
|
createObjectExpression,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
ForCodegenNode,
|
createSimpleExpression,
|
||||||
RenderSlotCall,
|
|
||||||
SlotOutletNode,
|
|
||||||
ElementNode,
|
|
||||||
DirectiveNode,
|
|
||||||
ForNode,
|
|
||||||
PlainElementNode,
|
|
||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
VNodeCall,
|
|
||||||
ForRenderListExpression,
|
|
||||||
BlockCodegenNode,
|
|
||||||
ForIteratorExpression,
|
|
||||||
ConstantTypes,
|
|
||||||
createBlockStatement,
|
|
||||||
createCompoundExpression,
|
|
||||||
getVNodeBlockHelper,
|
getVNodeBlockHelper,
|
||||||
getVNodeHelper,
|
getVNodeHelper,
|
||||||
ForParseResult
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import {
|
import {
|
||||||
|
findDir,
|
||||||
findProp,
|
findProp,
|
||||||
isTemplateNode,
|
|
||||||
isSlotOutlet,
|
|
||||||
injectProp,
|
injectProp,
|
||||||
findDir
|
isSlotOutlet,
|
||||||
|
isTemplateNode,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import {
|
import {
|
||||||
RENDER_LIST,
|
|
||||||
OPEN_BLOCK,
|
|
||||||
FRAGMENT,
|
FRAGMENT,
|
||||||
IS_MEMO_SAME
|
IS_MEMO_SAME,
|
||||||
|
OPEN_BLOCK,
|
||||||
|
RENDER_LIST,
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
import { validateBrowserExpression } from '../validateExpression'
|
import { validateBrowserExpression } from '../validateExpression'
|
||||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
import { PatchFlagNames, PatchFlags } from '@vue/shared'
|
||||||
|
|
||||||
export const transformFor = createStructuralDirectiveTransform(
|
export const transformFor = createStructuralDirectiveTransform(
|
||||||
'for',
|
'for',
|
||||||
|
@ -56,7 +56,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
// create the loop render function expression now, and add the
|
// create the loop render function expression now, and add the
|
||||||
// iterator on exit after all children have been traversed
|
// iterator on exit after all children have been traversed
|
||||||
const renderExp = createCallExpression(helper(RENDER_LIST), [
|
const renderExp = createCallExpression(helper(RENDER_LIST), [
|
||||||
forNode.source
|
forNode.source,
|
||||||
]) as ForRenderListExpression
|
]) as ForRenderListExpression
|
||||||
const isTemplate = isTemplateNode(node)
|
const isTemplate = isTemplateNode(node)
|
||||||
const memo = findDir(node, 'memo')
|
const memo = findDir(node, 'memo')
|
||||||
|
@ -76,13 +76,13 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
if (memo) {
|
if (memo) {
|
||||||
memo.exp = processExpression(
|
memo.exp = processExpression(
|
||||||
memo.exp! as SimpleExpressionNode,
|
memo.exp! as SimpleExpressionNode,
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (keyProperty && keyProp!.type !== NodeTypes.ATTRIBUTE) {
|
if (keyProperty && keyProp!.type !== NodeTypes.ATTRIBUTE) {
|
||||||
keyProperty.value = processExpression(
|
keyProperty.value = processExpression(
|
||||||
keyProperty.value as SimpleExpressionNode,
|
keyProperty.value as SimpleExpressionNode,
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +108,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
true /* isBlock */,
|
true /* isBlock */,
|
||||||
!isStableFragment /* disableTracking */,
|
!isStableFragment /* disableTracking */,
|
||||||
false /* isComponent */,
|
false /* isComponent */,
|
||||||
node.loc
|
node.loc,
|
||||||
) as ForCodegenNode
|
) as ForCodegenNode
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
@ -125,8 +125,8 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(
|
createCompilerError(
|
||||||
ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT,
|
ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT,
|
||||||
key.loc
|
key.loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
undefined,
|
undefined,
|
||||||
true,
|
true,
|
||||||
undefined,
|
undefined,
|
||||||
false /* isComponent */
|
false /* isComponent */,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// Normal element v-for. Directly use the child's codegenNode
|
// Normal element v-for. Directly use the child's codegenNode
|
||||||
|
@ -184,12 +184,12 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
// switch from block to vnode
|
// switch from block to vnode
|
||||||
removeHelper(OPEN_BLOCK)
|
removeHelper(OPEN_BLOCK)
|
||||||
removeHelper(
|
removeHelper(
|
||||||
getVNodeBlockHelper(context.inSSR, childBlock.isComponent)
|
getVNodeBlockHelper(context.inSSR, childBlock.isComponent),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
// switch from vnode to block
|
// switch from vnode to block
|
||||||
removeHelper(
|
removeHelper(
|
||||||
getVNodeHelper(context.inSSR, childBlock.isComponent)
|
getVNodeHelper(context.inSSR, childBlock.isComponent),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,8 +205,8 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
if (memo) {
|
if (memo) {
|
||||||
const loop = createFunctionExpression(
|
const loop = createFunctionExpression(
|
||||||
createForLoopParams(forNode.parseResult, [
|
createForLoopParams(forNode.parseResult, [
|
||||||
createSimpleExpression(`_cached`)
|
createSimpleExpression(`_cached`),
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
loop.body = createBlockStatement([
|
loop.body = createBlockStatement([
|
||||||
createCompoundExpression([`const _memo = (`, memo.exp!, `)`]),
|
createCompoundExpression([`const _memo = (`, memo.exp!, `)`]),
|
||||||
|
@ -214,30 +214,30 @@ export const transformFor = createStructuralDirectiveTransform(
|
||||||
`if (_cached`,
|
`if (_cached`,
|
||||||
...(keyExp ? [` && _cached.key === `, keyExp] : []),
|
...(keyExp ? [` && _cached.key === `, keyExp] : []),
|
||||||
` && ${context.helperString(
|
` && ${context.helperString(
|
||||||
IS_MEMO_SAME
|
IS_MEMO_SAME,
|
||||||
)}(_cached, _memo)) return _cached`
|
)}(_cached, _memo)) return _cached`,
|
||||||
]),
|
]),
|
||||||
createCompoundExpression([`const _item = `, childBlock as any]),
|
createCompoundExpression([`const _item = `, childBlock as any]),
|
||||||
createSimpleExpression(`_item.memo = _memo`),
|
createSimpleExpression(`_item.memo = _memo`),
|
||||||
createSimpleExpression(`return _item`)
|
createSimpleExpression(`return _item`),
|
||||||
])
|
])
|
||||||
renderExp.arguments.push(
|
renderExp.arguments.push(
|
||||||
loop as ForIteratorExpression,
|
loop as ForIteratorExpression,
|
||||||
createSimpleExpression(`_cache`),
|
createSimpleExpression(`_cache`),
|
||||||
createSimpleExpression(String(context.cached++))
|
createSimpleExpression(String(context.cached++)),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
renderExp.arguments.push(
|
renderExp.arguments.push(
|
||||||
createFunctionExpression(
|
createFunctionExpression(
|
||||||
createForLoopParams(forNode.parseResult),
|
createForLoopParams(forNode.parseResult),
|
||||||
childBlock,
|
childBlock,
|
||||||
true /* force newline */
|
true /* force newline */,
|
||||||
) as ForIteratorExpression
|
) as ForIteratorExpression,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// target-agnostic transform used for both Client and SSR
|
// target-agnostic transform used for both Client and SSR
|
||||||
|
@ -245,11 +245,11 @@ export function processFor(
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
dir: DirectiveNode,
|
dir: DirectiveNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
processCodegen?: (forNode: ForNode) => (() => void) | undefined
|
processCodegen?: (forNode: ForNode) => (() => void) | undefined,
|
||||||
) {
|
) {
|
||||||
if (!dir.exp) {
|
if (!dir.exp) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc)
|
createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ export function processFor(
|
||||||
|
|
||||||
if (!parseResult) {
|
if (!parseResult) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc)
|
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc),
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ export function processFor(
|
||||||
keyAlias: key,
|
keyAlias: key,
|
||||||
objectIndexAlias: index,
|
objectIndexAlias: index,
|
||||||
parseResult,
|
parseResult,
|
||||||
children: isTemplateNode(node) ? node.children : [node]
|
children: isTemplateNode(node) ? node.children : [node],
|
||||||
}
|
}
|
||||||
|
|
||||||
context.replaceNode(forNode)
|
context.replaceNode(forNode)
|
||||||
|
@ -306,34 +306,34 @@ export function processFor(
|
||||||
|
|
||||||
export function finalizeForParseResult(
|
export function finalizeForParseResult(
|
||||||
result: ForParseResult,
|
result: ForParseResult,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
) {
|
) {
|
||||||
if (result.finalized) return
|
if (result.finalized) return
|
||||||
|
|
||||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||||
result.source = processExpression(
|
result.source = processExpression(
|
||||||
result.source as SimpleExpressionNode,
|
result.source as SimpleExpressionNode,
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
if (result.key) {
|
if (result.key) {
|
||||||
result.key = processExpression(
|
result.key = processExpression(
|
||||||
result.key as SimpleExpressionNode,
|
result.key as SimpleExpressionNode,
|
||||||
context,
|
context,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (result.index) {
|
if (result.index) {
|
||||||
result.index = processExpression(
|
result.index = processExpression(
|
||||||
result.index as SimpleExpressionNode,
|
result.index as SimpleExpressionNode,
|
||||||
context,
|
context,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (result.value) {
|
if (result.value) {
|
||||||
result.value = processExpression(
|
result.value = processExpression(
|
||||||
result.value as SimpleExpressionNode,
|
result.value as SimpleExpressionNode,
|
||||||
context,
|
context,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,21 +343,21 @@ export function finalizeForParseResult(
|
||||||
validateBrowserExpression(
|
validateBrowserExpression(
|
||||||
result.key as SimpleExpressionNode,
|
result.key as SimpleExpressionNode,
|
||||||
context,
|
context,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (result.index) {
|
if (result.index) {
|
||||||
validateBrowserExpression(
|
validateBrowserExpression(
|
||||||
result.index as SimpleExpressionNode,
|
result.index as SimpleExpressionNode,
|
||||||
context,
|
context,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (result.value) {
|
if (result.value) {
|
||||||
validateBrowserExpression(
|
validateBrowserExpression(
|
||||||
result.value as SimpleExpressionNode,
|
result.value as SimpleExpressionNode,
|
||||||
context,
|
context,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -366,13 +366,13 @@ export function finalizeForParseResult(
|
||||||
|
|
||||||
export function createForLoopParams(
|
export function createForLoopParams(
|
||||||
{ value, key, index }: ForParseResult,
|
{ value, key, index }: ForParseResult,
|
||||||
memoArgs: ExpressionNode[] = []
|
memoArgs: ExpressionNode[] = [],
|
||||||
): ExpressionNode[] {
|
): ExpressionNode[] {
|
||||||
return createParamsList([value, key, index, ...memoArgs])
|
return createParamsList([value, key, index, ...memoArgs])
|
||||||
}
|
}
|
||||||
|
|
||||||
function createParamsList(
|
function createParamsList(
|
||||||
args: (ExpressionNode | undefined)[]
|
args: (ExpressionNode | undefined)[],
|
||||||
): ExpressionNode[] {
|
): ExpressionNode[] {
|
||||||
let i = args.length
|
let i = args.length
|
||||||
while (i--) {
|
while (i--) {
|
||||||
|
|
|
@ -1,37 +1,37 @@
|
||||||
import {
|
import {
|
||||||
|
type TransformContext,
|
||||||
createStructuralDirectiveTransform,
|
createStructuralDirectiveTransform,
|
||||||
TransformContext,
|
traverseNode,
|
||||||
traverseNode
|
|
||||||
} from '../transform'
|
} from '../transform'
|
||||||
import {
|
import {
|
||||||
NodeTypes,
|
type AttributeNode,
|
||||||
|
type BlockCodegenNode,
|
||||||
|
type CacheExpression,
|
||||||
|
ConstantTypes,
|
||||||
|
type DirectiveNode,
|
||||||
|
type ElementNode,
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
ElementNode,
|
type IfBranchNode,
|
||||||
DirectiveNode,
|
type IfConditionalExpression,
|
||||||
IfBranchNode,
|
type IfNode,
|
||||||
SimpleExpressionNode,
|
type MemoExpression,
|
||||||
|
NodeTypes,
|
||||||
|
type SimpleExpressionNode,
|
||||||
|
convertToBlock,
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
createConditionalExpression,
|
createConditionalExpression,
|
||||||
createSimpleExpression,
|
|
||||||
createObjectProperty,
|
|
||||||
createObjectExpression,
|
createObjectExpression,
|
||||||
IfConditionalExpression,
|
createObjectProperty,
|
||||||
BlockCodegenNode,
|
createSimpleExpression,
|
||||||
IfNode,
|
|
||||||
createVNodeCall,
|
createVNodeCall,
|
||||||
AttributeNode,
|
|
||||||
locStub,
|
locStub,
|
||||||
CacheExpression,
|
|
||||||
ConstantTypes,
|
|
||||||
MemoExpression,
|
|
||||||
convertToBlock
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
import { validateBrowserExpression } from '../validateExpression'
|
import { validateBrowserExpression } from '../validateExpression'
|
||||||
import { FRAGMENT, CREATE_COMMENT } from '../runtimeHelpers'
|
import { CREATE_COMMENT, FRAGMENT } from '../runtimeHelpers'
|
||||||
import { injectProp, findDir, findProp, getMemoedVNodeCall } from '../utils'
|
import { findDir, findProp, getMemoedVNodeCall, injectProp } from '../utils'
|
||||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
import { PatchFlagNames, PatchFlags } from '@vue/shared'
|
||||||
|
|
||||||
export const transformIf = createStructuralDirectiveTransform(
|
export const transformIf = createStructuralDirectiveTransform(
|
||||||
/^(if|else|else-if)$/,
|
/^(if|else|else-if)$/,
|
||||||
|
@ -57,7 +57,7 @@ export const transformIf = createStructuralDirectiveTransform(
|
||||||
ifNode.codegenNode = createCodegenNodeForBranch(
|
ifNode.codegenNode = createCodegenNodeForBranch(
|
||||||
branch,
|
branch,
|
||||||
key,
|
key,
|
||||||
context
|
context,
|
||||||
) as IfConditionalExpression
|
) as IfConditionalExpression
|
||||||
} else {
|
} else {
|
||||||
// attach this branch's codegen node to the v-if root.
|
// attach this branch's codegen node to the v-if root.
|
||||||
|
@ -65,12 +65,12 @@ export const transformIf = createStructuralDirectiveTransform(
|
||||||
parentCondition.alternate = createCodegenNodeForBranch(
|
parentCondition.alternate = createCodegenNodeForBranch(
|
||||||
branch,
|
branch,
|
||||||
key + ifNode.branches.length - 1,
|
key + ifNode.branches.length - 1,
|
||||||
context
|
context,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// target-agnostic transform used for both Client and SSR
|
// target-agnostic transform used for both Client and SSR
|
||||||
|
@ -81,8 +81,8 @@ export function processIf(
|
||||||
processCodegen?: (
|
processCodegen?: (
|
||||||
node: IfNode,
|
node: IfNode,
|
||||||
branch: IfBranchNode,
|
branch: IfBranchNode,
|
||||||
isRoot: boolean
|
isRoot: boolean,
|
||||||
) => (() => void) | undefined
|
) => (() => void) | undefined,
|
||||||
) {
|
) {
|
||||||
if (
|
if (
|
||||||
dir.name !== 'else' &&
|
dir.name !== 'else' &&
|
||||||
|
@ -90,7 +90,7 @@ export function processIf(
|
||||||
) {
|
) {
|
||||||
const loc = dir.exp ? dir.exp.loc : node.loc
|
const loc = dir.exp ? dir.exp.loc : node.loc
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_IF_NO_EXPRESSION, dir.loc)
|
createCompilerError(ErrorCodes.X_V_IF_NO_EXPRESSION, dir.loc),
|
||||||
)
|
)
|
||||||
dir.exp = createSimpleExpression(`true`, false, loc)
|
dir.exp = createSimpleExpression(`true`, false, loc)
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ export function processIf(
|
||||||
const ifNode: IfNode = {
|
const ifNode: IfNode = {
|
||||||
type: NodeTypes.IF,
|
type: NodeTypes.IF,
|
||||||
loc: node.loc,
|
loc: node.loc,
|
||||||
branches: [branch]
|
branches: [branch],
|
||||||
}
|
}
|
||||||
context.replaceNode(ifNode)
|
context.replaceNode(ifNode)
|
||||||
if (processCodegen) {
|
if (processCodegen) {
|
||||||
|
@ -145,7 +145,7 @@ export function processIf(
|
||||||
sibling.branches[sibling.branches.length - 1].condition === undefined
|
sibling.branches[sibling.branches.length - 1].condition === undefined
|
||||||
) {
|
) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc)
|
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,8 +175,8 @@ export function processIf(
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(
|
createCompilerError(
|
||||||
ErrorCodes.X_V_IF_SAME_KEY,
|
ErrorCodes.X_V_IF_SAME_KEY,
|
||||||
branch.userKey!.loc
|
branch.userKey!.loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -195,7 +195,7 @@ export function processIf(
|
||||||
context.currentNode = null
|
context.currentNode = null
|
||||||
} else {
|
} else {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc)
|
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
@ -211,14 +211,14 @@ function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
|
||||||
condition: dir.name === 'else' ? undefined : dir.exp,
|
condition: dir.name === 'else' ? undefined : dir.exp,
|
||||||
children: isTemplateIf && !findDir(node, 'for') ? node.children : [node],
|
children: isTemplateIf && !findDir(node, 'for') ? node.children : [node],
|
||||||
userKey: findProp(node, `key`),
|
userKey: findProp(node, `key`),
|
||||||
isTemplateIf
|
isTemplateIf,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createCodegenNodeForBranch(
|
function createCodegenNodeForBranch(
|
||||||
branch: IfBranchNode,
|
branch: IfBranchNode,
|
||||||
keyIndex: number,
|
keyIndex: number,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): IfConditionalExpression | BlockCodegenNode | MemoExpression {
|
): IfConditionalExpression | BlockCodegenNode | MemoExpression {
|
||||||
if (branch.condition) {
|
if (branch.condition) {
|
||||||
return createConditionalExpression(
|
return createConditionalExpression(
|
||||||
|
@ -228,8 +228,8 @@ function createCodegenNodeForBranch(
|
||||||
// closes the current block.
|
// closes the current block.
|
||||||
createCallExpression(context.helper(CREATE_COMMENT), [
|
createCallExpression(context.helper(CREATE_COMMENT), [
|
||||||
__DEV__ ? '"v-if"' : '""',
|
__DEV__ ? '"v-if"' : '""',
|
||||||
'true'
|
'true',
|
||||||
])
|
]),
|
||||||
) as IfConditionalExpression
|
) as IfConditionalExpression
|
||||||
} else {
|
} else {
|
||||||
return createChildrenCodegenNode(branch, keyIndex, context)
|
return createChildrenCodegenNode(branch, keyIndex, context)
|
||||||
|
@ -239,7 +239,7 @@ function createCodegenNodeForBranch(
|
||||||
function createChildrenCodegenNode(
|
function createChildrenCodegenNode(
|
||||||
branch: IfBranchNode,
|
branch: IfBranchNode,
|
||||||
keyIndex: number,
|
keyIndex: number,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): BlockCodegenNode | MemoExpression {
|
): BlockCodegenNode | MemoExpression {
|
||||||
const { helper } = context
|
const { helper } = context
|
||||||
const keyProperty = createObjectProperty(
|
const keyProperty = createObjectProperty(
|
||||||
|
@ -248,8 +248,8 @@ function createChildrenCodegenNode(
|
||||||
`${keyIndex}`,
|
`${keyIndex}`,
|
||||||
false,
|
false,
|
||||||
locStub,
|
locStub,
|
||||||
ConstantTypes.CAN_HOIST
|
ConstantTypes.CAN_HOIST,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
const { children } = branch
|
const { children } = branch
|
||||||
const firstChild = children[0]
|
const firstChild = children[0]
|
||||||
|
@ -286,7 +286,7 @@ function createChildrenCodegenNode(
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
false /* isComponent */,
|
false /* isComponent */,
|
||||||
branch.loc
|
branch.loc,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -306,7 +306,7 @@ function createChildrenCodegenNode(
|
||||||
|
|
||||||
function isSameKey(
|
function isSameKey(
|
||||||
a: AttributeNode | DirectiveNode | undefined,
|
a: AttributeNode | DirectiveNode | undefined,
|
||||||
b: AttributeNode | DirectiveNode
|
b: AttributeNode | DirectiveNode,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (!a || a.type !== b.type) {
|
if (!a || a.type !== b.type) {
|
||||||
return false
|
return false
|
||||||
|
@ -334,7 +334,7 @@ function isSameKey(
|
||||||
}
|
}
|
||||||
|
|
||||||
function getParentCondition(
|
function getParentCondition(
|
||||||
node: IfConditionalExpression | CacheExpression
|
node: IfConditionalExpression | CacheExpression,
|
||||||
): IfConditionalExpression {
|
): IfConditionalExpression {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (node.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) {
|
if (node.type === NodeTypes.JS_CONDITIONAL_EXPRESSION) {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { NodeTransform } from '../transform'
|
import type { NodeTransform } from '../transform'
|
||||||
import { findDir } from '../utils'
|
import { findDir } from '../utils'
|
||||||
import {
|
import {
|
||||||
|
ElementTypes,
|
||||||
|
type MemoExpression,
|
||||||
|
NodeTypes,
|
||||||
|
type PlainElementNode,
|
||||||
convertToBlock,
|
convertToBlock,
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
createFunctionExpression,
|
createFunctionExpression,
|
||||||
ElementTypes,
|
|
||||||
MemoExpression,
|
|
||||||
NodeTypes,
|
|
||||||
PlainElementNode
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { WITH_MEMO } from '../runtimeHelpers'
|
import { WITH_MEMO } from '../runtimeHelpers'
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export const transformMemo: NodeTransform = (node, context) => {
|
||||||
dir.exp!,
|
dir.exp!,
|
||||||
createFunctionExpression(undefined, codegenNode),
|
createFunctionExpression(undefined, codegenNode),
|
||||||
`_cache`,
|
`_cache`,
|
||||||
String(context.cached++)
|
String(context.cached++),
|
||||||
]) as MemoExpression
|
]) as MemoExpression
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import { DirectiveTransform } from '../transform'
|
import type { DirectiveTransform } from '../transform'
|
||||||
import {
|
import {
|
||||||
createSimpleExpression,
|
ConstantTypes,
|
||||||
createObjectProperty,
|
|
||||||
createCompoundExpression,
|
|
||||||
NodeTypes,
|
|
||||||
Property,
|
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
ExpressionNode,
|
type ExpressionNode,
|
||||||
ConstantTypes
|
NodeTypes,
|
||||||
|
type Property,
|
||||||
|
createCompoundExpression,
|
||||||
|
createObjectProperty,
|
||||||
|
createSimpleExpression,
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import {
|
import {
|
||||||
|
hasScopeRef,
|
||||||
isMemberExpression,
|
isMemberExpression,
|
||||||
isSimpleIdentifier,
|
isSimpleIdentifier,
|
||||||
hasScopeRef,
|
isStaticExp,
|
||||||
isStaticExp
|
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { IS_REF } from '../runtimeHelpers'
|
import { IS_REF } from '../runtimeHelpers'
|
||||||
import { BindingTypes } from '../options'
|
import { BindingTypes } from '../options'
|
||||||
|
@ -24,7 +24,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
const { exp, arg } = dir
|
const { exp, arg } = dir
|
||||||
if (!exp) {
|
if (!exp) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_MODEL_NO_EXPRESSION, dir.loc)
|
createCompilerError(ErrorCodes.X_V_MODEL_NO_EXPRESSION, dir.loc),
|
||||||
)
|
)
|
||||||
return createTransformProps()
|
return createTransformProps()
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
(!isMemberExpression(expString, context) && !maybeRef)
|
(!isMemberExpression(expString, context) && !maybeRef)
|
||||||
) {
|
) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc)
|
createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc),
|
||||||
)
|
)
|
||||||
return createTransformProps()
|
return createTransformProps()
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
context.identifiers[expString]
|
context.identifiers[expString]
|
||||||
) {
|
) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE, exp.loc)
|
createCompilerError(ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE, exp.loc),
|
||||||
)
|
)
|
||||||
return createTransformProps()
|
return createTransformProps()
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
assignmentExp = createCompoundExpression([
|
assignmentExp = createCompoundExpression([
|
||||||
`${eventArg} => ((`,
|
`${eventArg} => ((`,
|
||||||
createSimpleExpression(rawExp, false, exp.loc),
|
createSimpleExpression(rawExp, false, exp.loc),
|
||||||
`).value = $event)`
|
`).value = $event)`,
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
// v-model used on a potentially ref binding in <script setup> inline mode.
|
// v-model used on a potentially ref binding in <script setup> inline mode.
|
||||||
|
@ -102,14 +102,14 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
assignmentExp = createCompoundExpression([
|
assignmentExp = createCompoundExpression([
|
||||||
`${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,
|
`${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,
|
||||||
createSimpleExpression(rawExp, false, exp.loc),
|
createSimpleExpression(rawExp, false, exp.loc),
|
||||||
`).value = $event : ${altAssignment})`
|
`).value = $event : ${altAssignment})`,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
assignmentExp = createCompoundExpression([
|
assignmentExp = createCompoundExpression([
|
||||||
`${eventArg} => ((`,
|
`${eventArg} => ((`,
|
||||||
exp,
|
exp,
|
||||||
`) = $event)`
|
`) = $event)`,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
// modelValue: foo
|
// modelValue: foo
|
||||||
createObjectProperty(propName, dir.exp!),
|
createObjectProperty(propName, dir.exp!),
|
||||||
// "onUpdate:modelValue": $event => (foo = $event)
|
// "onUpdate:modelValue": $event => (foo = $event)
|
||||||
createObjectProperty(eventName, assignmentExp)
|
createObjectProperty(eventName, assignmentExp),
|
||||||
]
|
]
|
||||||
|
|
||||||
// cache v-model handler if applicable (when it doesn't refer any scope vars)
|
// cache v-model handler if applicable (when it doesn't refer any scope vars)
|
||||||
|
@ -148,9 +148,9 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
`{ ${modifiers} }`,
|
`{ ${modifiers} }`,
|
||||||
false,
|
false,
|
||||||
dir.loc,
|
dir.loc,
|
||||||
ConstantTypes.CAN_HOIST
|
ConstantTypes.CAN_HOIST,
|
||||||
)
|
),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
import { DirectiveTransform, DirectiveTransformResult } from '../transform'
|
import type { DirectiveTransform, DirectiveTransformResult } from '../transform'
|
||||||
import {
|
import {
|
||||||
|
type DirectiveNode,
|
||||||
|
ElementTypes,
|
||||||
|
type ExpressionNode,
|
||||||
|
NodeTypes,
|
||||||
|
type SimpleExpressionNode,
|
||||||
createCompoundExpression,
|
createCompoundExpression,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
DirectiveNode,
|
|
||||||
ElementTypes,
|
|
||||||
ExpressionNode,
|
|
||||||
NodeTypes,
|
|
||||||
SimpleExpressionNode
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { camelize, toHandlerKey } from '@vue/shared'
|
import { camelize, toHandlerKey } from '@vue/shared'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import { processExpression } from './transformExpression'
|
import { processExpression } from './transformExpression'
|
||||||
import { validateBrowserExpression } from '../validateExpression'
|
import { validateBrowserExpression } from '../validateExpression'
|
||||||
import { hasScopeRef, isMemberExpression } from '../utils'
|
import { hasScopeRef, isMemberExpression } from '../utils'
|
||||||
|
@ -33,7 +33,7 @@ export const transformOn: DirectiveTransform = (
|
||||||
dir,
|
dir,
|
||||||
node,
|
node,
|
||||||
context,
|
context,
|
||||||
augmentor
|
augmentor,
|
||||||
) => {
|
) => {
|
||||||
const { loc, modifiers, arg } = dir as VOnDirectiveNode
|
const { loc, modifiers, arg } = dir as VOnDirectiveNode
|
||||||
if (!dir.exp && !modifiers.length) {
|
if (!dir.exp && !modifiers.length) {
|
||||||
|
@ -65,7 +65,7 @@ export const transformOn: DirectiveTransform = (
|
||||||
eventName = createCompoundExpression([
|
eventName = createCompoundExpression([
|
||||||
`${context.helperString(TO_HANDLER_KEY)}(`,
|
`${context.helperString(TO_HANDLER_KEY)}(`,
|
||||||
arg,
|
arg,
|
||||||
`)`
|
`)`,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,7 +95,7 @@ export const transformOn: DirectiveTransform = (
|
||||||
exp,
|
exp,
|
||||||
context,
|
context,
|
||||||
false,
|
false,
|
||||||
hasMultipleStatements
|
hasMultipleStatements,
|
||||||
)
|
)
|
||||||
isInlineStatement && context.removeIdentifiers(`$event`)
|
isInlineStatement && context.removeIdentifiers(`$event`)
|
||||||
// with scope analysis, the function is hoistable if it has no reference
|
// with scope analysis, the function is hoistable if it has no reference
|
||||||
|
@ -134,7 +134,7 @@ export const transformOn: DirectiveTransform = (
|
||||||
exp as SimpleExpressionNode,
|
exp as SimpleExpressionNode,
|
||||||
context,
|
context,
|
||||||
false,
|
false,
|
||||||
hasMultipleStatements
|
hasMultipleStatements,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ export const transformOn: DirectiveTransform = (
|
||||||
}(...args)`
|
}(...args)`
|
||||||
} => ${hasMultipleStatements ? `{` : `(`}`,
|
} => ${hasMultipleStatements ? `{` : `(`}`,
|
||||||
exp,
|
exp,
|
||||||
hasMultipleStatements ? `}` : `)`
|
hasMultipleStatements ? `}` : `)`,
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,9 +160,9 @@ export const transformOn: DirectiveTransform = (
|
||||||
props: [
|
props: [
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
eventName,
|
eventName,
|
||||||
exp || createSimpleExpression(`() => {}`, false, loc)
|
exp || createSimpleExpression(`() => {}`, false, loc),
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply extended compiler augmentor
|
// apply extended compiler augmentor
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { NodeTransform } from '../transform'
|
import type { NodeTransform } from '../transform'
|
||||||
import { findDir } from '../utils'
|
import { findDir } from '../utils'
|
||||||
import { ElementNode, ForNode, IfNode, NodeTypes } from '../ast'
|
import { type ElementNode, type ForNode, type IfNode, NodeTypes } from '../ast'
|
||||||
import { SET_BLOCK_TRACKING } from '../runtimeHelpers'
|
import { SET_BLOCK_TRACKING } from '../runtimeHelpers'
|
||||||
|
|
||||||
const seen = new WeakSet()
|
const seen = new WeakSet()
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
import {
|
import {
|
||||||
ElementNode,
|
type CallExpression,
|
||||||
ObjectExpression,
|
type ConditionalExpression,
|
||||||
createObjectExpression,
|
type DirectiveNode,
|
||||||
|
type ElementNode,
|
||||||
|
ElementTypes,
|
||||||
|
type ExpressionNode,
|
||||||
|
type FunctionExpression,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
|
type ObjectExpression,
|
||||||
|
type Property,
|
||||||
|
type SlotsExpression,
|
||||||
|
type SourceLocation,
|
||||||
|
type TemplateChildNode,
|
||||||
|
createArrayExpression,
|
||||||
|
createCallExpression,
|
||||||
|
createConditionalExpression,
|
||||||
|
createFunctionExpression,
|
||||||
|
createObjectExpression,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
createFunctionExpression,
|
|
||||||
DirectiveNode,
|
|
||||||
ElementTypes,
|
|
||||||
ExpressionNode,
|
|
||||||
Property,
|
|
||||||
TemplateChildNode,
|
|
||||||
SourceLocation,
|
|
||||||
createConditionalExpression,
|
|
||||||
ConditionalExpression,
|
|
||||||
FunctionExpression,
|
|
||||||
CallExpression,
|
|
||||||
createCallExpression,
|
|
||||||
createArrayExpression,
|
|
||||||
SlotsExpression
|
|
||||||
} from '../ast'
|
} from '../ast'
|
||||||
import { TransformContext, NodeTransform } from '../transform'
|
import type { NodeTransform, TransformContext } from '../transform'
|
||||||
import { createCompilerError, ErrorCodes } from '../errors'
|
import { ErrorCodes, createCompilerError } from '../errors'
|
||||||
import {
|
import {
|
||||||
findDir,
|
|
||||||
isTemplateNode,
|
|
||||||
assert,
|
assert,
|
||||||
isVSlot,
|
findDir,
|
||||||
hasScopeRef,
|
hasScopeRef,
|
||||||
isStaticExp
|
isStaticExp,
|
||||||
|
isTemplateNode,
|
||||||
|
isVSlot,
|
||||||
} from '../utils'
|
} from '../utils'
|
||||||
import { CREATE_SLOTS, RENDER_LIST, WITH_CTX } from '../runtimeHelpers'
|
import { CREATE_SLOTS, RENDER_LIST, WITH_CTX } from '../runtimeHelpers'
|
||||||
import { createForLoopParams, finalizeForParseResult } from './vFor'
|
import { createForLoopParams, finalizeForParseResult } from './vFor'
|
||||||
|
@ -99,7 +99,7 @@ export type SlotFnBuilder = (
|
||||||
slotProps: ExpressionNode | undefined,
|
slotProps: ExpressionNode | undefined,
|
||||||
vFor: DirectiveNode | undefined,
|
vFor: DirectiveNode | undefined,
|
||||||
slotChildren: TemplateChildNode[],
|
slotChildren: TemplateChildNode[],
|
||||||
loc: SourceLocation
|
loc: SourceLocation,
|
||||||
) => FunctionExpression
|
) => FunctionExpression
|
||||||
|
|
||||||
const buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>
|
const buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>
|
||||||
|
@ -108,7 +108,7 @@ const buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>
|
||||||
children,
|
children,
|
||||||
false /* newline */,
|
false /* newline */,
|
||||||
true /* isSlot */,
|
true /* isSlot */,
|
||||||
children.length ? children[0].loc : loc
|
children.length ? children[0].loc : loc,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Instead of being a DirectiveTransform, v-slot processing is called during
|
// Instead of being a DirectiveTransform, v-slot processing is called during
|
||||||
|
@ -116,7 +116,7 @@ const buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>
|
||||||
export function buildSlots(
|
export function buildSlots(
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
buildSlotFn: SlotFnBuilder = buildClientSlotFn
|
buildSlotFn: SlotFnBuilder = buildClientSlotFn,
|
||||||
): {
|
): {
|
||||||
slots: SlotsExpression
|
slots: SlotsExpression
|
||||||
hasDynamicSlots: boolean
|
hasDynamicSlots: boolean
|
||||||
|
@ -147,8 +147,8 @@ export function buildSlots(
|
||||||
slotsProperties.push(
|
slotsProperties.push(
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
arg || createSimpleExpression('default', true),
|
arg || createSimpleExpression('default', true),
|
||||||
buildSlotFn(exp, undefined, children, loc)
|
buildSlotFn(exp, undefined, children, loc),
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ export function buildSlots(
|
||||||
if (onComponentSlot) {
|
if (onComponentSlot) {
|
||||||
// already has on-component slot - this is incorrect usage.
|
// already has on-component slot - this is incorrect usage.
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc)
|
createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc),
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ export function buildSlots(
|
||||||
const {
|
const {
|
||||||
arg: slotName = createSimpleExpression(`default`, true),
|
arg: slotName = createSimpleExpression(`default`, true),
|
||||||
exp: slotProps,
|
exp: slotProps,
|
||||||
loc: dirLoc
|
loc: dirLoc,
|
||||||
} = slotDir
|
} = slotDir
|
||||||
|
|
||||||
// check if name is dynamic.
|
// check if name is dynamic.
|
||||||
|
@ -211,8 +211,8 @@ export function buildSlots(
|
||||||
createConditionalExpression(
|
createConditionalExpression(
|
||||||
vIf.exp!,
|
vIf.exp!,
|
||||||
buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++),
|
buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++),
|
||||||
defaultFallback
|
defaultFallback,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
} else if (
|
} else if (
|
||||||
(vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))
|
(vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))
|
||||||
|
@ -246,14 +246,14 @@ export function buildSlots(
|
||||||
buildDynamicSlot(
|
buildDynamicSlot(
|
||||||
slotName,
|
slotName,
|
||||||
slotFunction,
|
slotFunction,
|
||||||
conditionalBranchIndex++
|
conditionalBranchIndex++,
|
||||||
),
|
),
|
||||||
defaultFallback
|
defaultFallback,
|
||||||
)
|
)
|
||||||
: buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++)
|
: buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++)
|
||||||
} else {
|
} else {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, vElse.loc)
|
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, vElse.loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (vFor) {
|
} else if (vFor) {
|
||||||
|
@ -269,13 +269,16 @@ export function buildSlots(
|
||||||
createFunctionExpression(
|
createFunctionExpression(
|
||||||
createForLoopParams(parseResult),
|
createForLoopParams(parseResult),
|
||||||
buildDynamicSlot(slotName, slotFunction),
|
buildDynamicSlot(slotName, slotFunction),
|
||||||
true /* force newline */
|
true /* force newline */,
|
||||||
)
|
),
|
||||||
])
|
]),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, vFor.loc)
|
createCompilerError(
|
||||||
|
ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,
|
||||||
|
vFor.loc,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -285,8 +288,8 @@ export function buildSlots(
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(
|
createCompilerError(
|
||||||
ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES,
|
ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES,
|
||||||
dirLoc
|
dirLoc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -302,7 +305,7 @@ export function buildSlots(
|
||||||
if (!onComponentSlot) {
|
if (!onComponentSlot) {
|
||||||
const buildDefaultSlotProperty = (
|
const buildDefaultSlotProperty = (
|
||||||
props: ExpressionNode | undefined,
|
props: ExpressionNode | undefined,
|
||||||
children: TemplateChildNode[]
|
children: TemplateChildNode[],
|
||||||
) => {
|
) => {
|
||||||
const fn = buildSlotFn(props, undefined, children, loc)
|
const fn = buildSlotFn(props, undefined, children, loc)
|
||||||
if (__COMPAT__ && context.compatConfig) {
|
if (__COMPAT__ && context.compatConfig) {
|
||||||
|
@ -326,12 +329,12 @@ export function buildSlots(
|
||||||
context.onError(
|
context.onError(
|
||||||
createCompilerError(
|
createCompilerError(
|
||||||
ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,
|
ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,
|
||||||
implicitDefaultChildren[0].loc
|
implicitDefaultChildren[0].loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
slotsProperties.push(
|
slotsProperties.push(
|
||||||
buildDefaultSlotProperty(undefined, implicitDefaultChildren)
|
buildDefaultSlotProperty(undefined, implicitDefaultChildren),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,37 +354,37 @@ export function buildSlots(
|
||||||
// 1 = compiled and static = can skip normalization AND diff as optimized
|
// 1 = compiled and static = can skip normalization AND diff as optimized
|
||||||
createSimpleExpression(
|
createSimpleExpression(
|
||||||
slotFlag + (__DEV__ ? ` /* ${slotFlagsText[slotFlag]} */` : ``),
|
slotFlag + (__DEV__ ? ` /* ${slotFlagsText[slotFlag]} */` : ``),
|
||||||
false
|
false,
|
||||||
)
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
loc
|
),
|
||||||
|
),
|
||||||
|
loc,
|
||||||
) as SlotsExpression
|
) as SlotsExpression
|
||||||
if (dynamicSlots.length) {
|
if (dynamicSlots.length) {
|
||||||
slots = createCallExpression(context.helper(CREATE_SLOTS), [
|
slots = createCallExpression(context.helper(CREATE_SLOTS), [
|
||||||
slots,
|
slots,
|
||||||
createArrayExpression(dynamicSlots)
|
createArrayExpression(dynamicSlots),
|
||||||
]) as SlotsExpression
|
]) as SlotsExpression
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
slots,
|
slots,
|
||||||
hasDynamicSlots
|
hasDynamicSlots,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDynamicSlot(
|
function buildDynamicSlot(
|
||||||
name: ExpressionNode,
|
name: ExpressionNode,
|
||||||
fn: FunctionExpression,
|
fn: FunctionExpression,
|
||||||
index?: number
|
index?: number,
|
||||||
): ObjectExpression {
|
): ObjectExpression {
|
||||||
const props = [
|
const props = [
|
||||||
createObjectProperty(`name`, name),
|
createObjectProperty(`name`, name),
|
||||||
createObjectProperty(`fn`, fn)
|
createObjectProperty(`fn`, fn),
|
||||||
]
|
]
|
||||||
if (index != null) {
|
if (index != null) {
|
||||||
props.push(
|
props.push(
|
||||||
createObjectProperty(`key`, createSimpleExpression(String(index), true))
|
createObjectProperty(`key`, createSimpleExpression(String(index), true)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return createObjectExpression(props)
|
return createObjectExpression(props)
|
||||||
|
|
|
@ -1,45 +1,45 @@
|
||||||
import {
|
import {
|
||||||
Position,
|
type BlockCodegenNode,
|
||||||
ElementNode,
|
type CallExpression,
|
||||||
NodeTypes,
|
type DirectiveNode,
|
||||||
CallExpression,
|
type ElementNode,
|
||||||
createCallExpression,
|
|
||||||
DirectiveNode,
|
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
TemplateChildNode,
|
type ExpressionNode,
|
||||||
RootNode,
|
type IfBranchNode,
|
||||||
ObjectExpression,
|
type InterpolationNode,
|
||||||
Property,
|
type JSChildNode,
|
||||||
JSChildNode,
|
type MemoExpression,
|
||||||
|
NodeTypes,
|
||||||
|
type ObjectExpression,
|
||||||
|
type Position,
|
||||||
|
type Property,
|
||||||
|
type RenderSlotCall,
|
||||||
|
type RootNode,
|
||||||
|
type SimpleExpressionNode,
|
||||||
|
type SlotOutletNode,
|
||||||
|
type TemplateChildNode,
|
||||||
|
type TemplateNode,
|
||||||
|
type TextNode,
|
||||||
|
type VNodeCall,
|
||||||
|
createCallExpression,
|
||||||
createObjectExpression,
|
createObjectExpression,
|
||||||
SlotOutletNode,
|
|
||||||
TemplateNode,
|
|
||||||
RenderSlotCall,
|
|
||||||
ExpressionNode,
|
|
||||||
IfBranchNode,
|
|
||||||
TextNode,
|
|
||||||
InterpolationNode,
|
|
||||||
VNodeCall,
|
|
||||||
SimpleExpressionNode,
|
|
||||||
BlockCodegenNode,
|
|
||||||
MemoExpression
|
|
||||||
} from './ast'
|
} from './ast'
|
||||||
import { TransformContext } from './transform'
|
import type { TransformContext } from './transform'
|
||||||
import {
|
import {
|
||||||
MERGE_PROPS,
|
|
||||||
TELEPORT,
|
|
||||||
SUSPENSE,
|
|
||||||
KEEP_ALIVE,
|
|
||||||
BASE_TRANSITION,
|
BASE_TRANSITION,
|
||||||
TO_HANDLERS,
|
|
||||||
NORMALIZE_PROPS,
|
|
||||||
GUARD_REACTIVE_PROPS,
|
GUARD_REACTIVE_PROPS,
|
||||||
WITH_MEMO
|
KEEP_ALIVE,
|
||||||
|
MERGE_PROPS,
|
||||||
|
NORMALIZE_PROPS,
|
||||||
|
SUSPENSE,
|
||||||
|
TELEPORT,
|
||||||
|
TO_HANDLERS,
|
||||||
|
WITH_MEMO,
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { isString, isObject, NOOP } from '@vue/shared'
|
import { NOOP, isObject, isString } from '@vue/shared'
|
||||||
import { PropsExpression } from './transforms/transformElement'
|
import type { PropsExpression } from './transforms/transformElement'
|
||||||
import { parseExpression } from '@babel/parser'
|
import { parseExpression } from '@babel/parser'
|
||||||
import { Expression } from '@babel/types'
|
import type { Expression } from '@babel/types'
|
||||||
import { unwrapTSNode } from './babelUtils'
|
import { unwrapTSNode } from './babelUtils'
|
||||||
|
|
||||||
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
||||||
|
@ -70,7 +70,7 @@ enum MemberExpLexState {
|
||||||
inMemberExp,
|
inMemberExp,
|
||||||
inBrackets,
|
inBrackets,
|
||||||
inParens,
|
inParens,
|
||||||
inString
|
inString,
|
||||||
}
|
}
|
||||||
|
|
||||||
const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/
|
const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/
|
||||||
|
@ -157,7 +157,7 @@ export const isMemberExpressionNode = __BROWSER__
|
||||||
: (path: string, context: TransformContext): boolean => {
|
: (path: string, context: TransformContext): boolean => {
|
||||||
try {
|
try {
|
||||||
let ret: Expression = parseExpression(path, {
|
let ret: Expression = parseExpression(path, {
|
||||||
plugins: context.expressionPlugins
|
plugins: context.expressionPlugins,
|
||||||
})
|
})
|
||||||
ret = unwrapTSNode(ret) as Expression
|
ret = unwrapTSNode(ret) as Expression
|
||||||
return (
|
return (
|
||||||
|
@ -177,16 +177,16 @@ export const isMemberExpression = __BROWSER__
|
||||||
export function advancePositionWithClone(
|
export function advancePositionWithClone(
|
||||||
pos: Position,
|
pos: Position,
|
||||||
source: string,
|
source: string,
|
||||||
numberOfCharacters: number = source.length
|
numberOfCharacters: number = source.length,
|
||||||
): Position {
|
): Position {
|
||||||
return advancePositionWithMutation(
|
return advancePositionWithMutation(
|
||||||
{
|
{
|
||||||
offset: pos.offset,
|
offset: pos.offset,
|
||||||
line: pos.line,
|
line: pos.line,
|
||||||
column: pos.column
|
column: pos.column,
|
||||||
},
|
},
|
||||||
source,
|
source,
|
||||||
numberOfCharacters
|
numberOfCharacters,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ export function advancePositionWithClone(
|
||||||
export function advancePositionWithMutation(
|
export function advancePositionWithMutation(
|
||||||
pos: Position,
|
pos: Position,
|
||||||
source: string,
|
source: string,
|
||||||
numberOfCharacters: number = source.length
|
numberOfCharacters: number = source.length,
|
||||||
): Position {
|
): Position {
|
||||||
let linesCount = 0
|
let linesCount = 0
|
||||||
let lastNewLinePos = -1
|
let lastNewLinePos = -1
|
||||||
|
@ -226,7 +226,7 @@ export function assert(condition: boolean, msg?: string) {
|
||||||
export function findDir(
|
export function findDir(
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
name: string | RegExp,
|
name: string | RegExp,
|
||||||
allowEmpty: boolean = false
|
allowEmpty: boolean = false,
|
||||||
): DirectiveNode | undefined {
|
): DirectiveNode | undefined {
|
||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const p = node.props[i]
|
const p = node.props[i]
|
||||||
|
@ -244,7 +244,7 @@ export function findProp(
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
name: string,
|
name: string,
|
||||||
dynamicOnly: boolean = false,
|
dynamicOnly: boolean = false,
|
||||||
allowEmpty: boolean = false
|
allowEmpty: boolean = false,
|
||||||
): ElementNode['props'][0] | undefined {
|
): ElementNode['props'][0] | undefined {
|
||||||
for (let i = 0; i < node.props.length; i++) {
|
for (let i = 0; i < node.props.length; i++) {
|
||||||
const p = node.props[i]
|
const p = node.props[i]
|
||||||
|
@ -265,7 +265,7 @@ export function findProp(
|
||||||
|
|
||||||
export function isStaticArgOf(
|
export function isStaticArgOf(
|
||||||
arg: DirectiveNode['arg'],
|
arg: DirectiveNode['arg'],
|
||||||
name: string
|
name: string,
|
||||||
): boolean {
|
): boolean {
|
||||||
return !!(arg && isStaticExp(arg) && arg.content === name)
|
return !!(arg && isStaticExp(arg) && arg.content === name)
|
||||||
}
|
}
|
||||||
|
@ -277,12 +277,12 @@ export function hasDynamicKeyVBind(node: ElementNode): boolean {
|
||||||
p.name === 'bind' &&
|
p.name === 'bind' &&
|
||||||
(!p.arg || // v-bind="obj"
|
(!p.arg || // v-bind="obj"
|
||||||
p.arg.type !== NodeTypes.SIMPLE_EXPRESSION || // v-bind:[_ctx.foo]
|
p.arg.type !== NodeTypes.SIMPLE_EXPRESSION || // v-bind:[_ctx.foo]
|
||||||
!p.arg.isStatic) // v-bind:[foo]
|
!p.arg.isStatic), // v-bind:[foo]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isText(
|
export function isText(
|
||||||
node: TemplateChildNode
|
node: TemplateChildNode,
|
||||||
): node is TextNode | InterpolationNode {
|
): node is TextNode | InterpolationNode {
|
||||||
return node.type === NodeTypes.INTERPOLATION || node.type === NodeTypes.TEXT
|
return node.type === NodeTypes.INTERPOLATION || node.type === NodeTypes.TEXT
|
||||||
}
|
}
|
||||||
|
@ -292,7 +292,7 @@ export function isVSlot(p: ElementNode['props'][0]): p is DirectiveNode {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isTemplateNode(
|
export function isTemplateNode(
|
||||||
node: RootNode | TemplateChildNode
|
node: RootNode | TemplateChildNode,
|
||||||
): node is TemplateNode {
|
): node is TemplateNode {
|
||||||
return (
|
return (
|
||||||
node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE
|
node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE
|
||||||
|
@ -300,7 +300,7 @@ export function isTemplateNode(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isSlotOutlet(
|
export function isSlotOutlet(
|
||||||
node: RootNode | TemplateChildNode
|
node: RootNode | TemplateChildNode,
|
||||||
): node is SlotOutletNode {
|
): node is SlotOutletNode {
|
||||||
return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
|
return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
|
||||||
}
|
}
|
||||||
|
@ -309,7 +309,7 @@ const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS])
|
||||||
|
|
||||||
function getUnnormalizedProps(
|
function getUnnormalizedProps(
|
||||||
props: PropsExpression | '{}',
|
props: PropsExpression | '{}',
|
||||||
callPath: CallExpression[] = []
|
callPath: CallExpression[] = [],
|
||||||
): [PropsExpression | '{}', CallExpression[]] {
|
): [PropsExpression | '{}', CallExpression[]] {
|
||||||
if (
|
if (
|
||||||
props &&
|
props &&
|
||||||
|
@ -320,7 +320,7 @@ function getUnnormalizedProps(
|
||||||
if (!isString(callee) && propsHelperSet.has(callee)) {
|
if (!isString(callee) && propsHelperSet.has(callee)) {
|
||||||
return getUnnormalizedProps(
|
return getUnnormalizedProps(
|
||||||
props.arguments[0] as PropsExpression,
|
props.arguments[0] as PropsExpression,
|
||||||
callPath.concat(props)
|
callPath.concat(props),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ function getUnnormalizedProps(
|
||||||
export function injectProp(
|
export function injectProp(
|
||||||
node: VNodeCall | RenderSlotCall,
|
node: VNodeCall | RenderSlotCall,
|
||||||
prop: Property,
|
prop: Property,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
) {
|
) {
|
||||||
let propsWithInjection: ObjectExpression | CallExpression | undefined
|
let propsWithInjection: ObjectExpression | CallExpression | undefined
|
||||||
/**
|
/**
|
||||||
|
@ -372,7 +372,7 @@ export function injectProp(
|
||||||
// #2366
|
// #2366
|
||||||
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
|
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
|
||||||
createObjectExpression([prop]),
|
createObjectExpression([prop]),
|
||||||
props
|
props,
|
||||||
])
|
])
|
||||||
} else {
|
} else {
|
||||||
props.arguments.unshift(createObjectExpression([prop]))
|
props.arguments.unshift(createObjectExpression([prop]))
|
||||||
|
@ -388,7 +388,7 @@ export function injectProp(
|
||||||
// single v-bind with expression, return a merged replacement
|
// single v-bind with expression, return a merged replacement
|
||||||
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
|
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
|
||||||
createObjectExpression([prop]),
|
createObjectExpression([prop]),
|
||||||
props
|
props,
|
||||||
])
|
])
|
||||||
// in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`,
|
// in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(props))`,
|
||||||
// it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`,
|
// it will be rewritten as `normalizeProps(mergeProps({ key: 0 }, props))`,
|
||||||
|
@ -420,7 +420,7 @@ function hasProp(prop: Property, props: ObjectExpression) {
|
||||||
result = props.properties.some(
|
result = props.properties.some(
|
||||||
p =>
|
p =>
|
||||||
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
|
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
|
||||||
p.key.content === propKeyName
|
p.key.content === propKeyName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
@ -428,7 +428,7 @@ function hasProp(prop: Property, props: ObjectExpression) {
|
||||||
|
|
||||||
export function toValidAssetId(
|
export function toValidAssetId(
|
||||||
name: string,
|
name: string,
|
||||||
type: 'component' | 'directive' | 'filter'
|
type: 'component' | 'directive' | 'filter',
|
||||||
): string {
|
): string {
|
||||||
// see issue#4422, we need adding identifier on validAssetId if variable `name` has specific character
|
// see issue#4422, we need adding identifier on validAssetId if variable `name` has specific character
|
||||||
return `_${type}_${name.replace(/[^\w]/g, (searchValue, replaceValue) => {
|
return `_${type}_${name.replace(/[^\w]/g, (searchValue, replaceValue) => {
|
||||||
|
@ -439,7 +439,7 @@ export function toValidAssetId(
|
||||||
// Check if a node contains expressions that reference current context scope ids
|
// Check if a node contains expressions that reference current context scope ids
|
||||||
export function hasScopeRef(
|
export function hasScopeRef(
|
||||||
node: TemplateChildNode | IfBranchNode | ExpressionNode | undefined,
|
node: TemplateChildNode | IfBranchNode | ExpressionNode | undefined,
|
||||||
ids: TransformContext['identifiers']
|
ids: TransformContext['identifiers'],
|
||||||
): boolean {
|
): boolean {
|
||||||
if (!node || Object.keys(ids).length === 0) {
|
if (!node || Object.keys(ids).length === 0) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { SimpleExpressionNode } from './ast'
|
import type { SimpleExpressionNode } from './ast'
|
||||||
import { TransformContext } from './transform'
|
import type { TransformContext } from './transform'
|
||||||
import { createCompilerError, ErrorCodes } from './errors'
|
import { ErrorCodes, createCompilerError } from './errors'
|
||||||
|
|
||||||
// these keywords should not appear inside expressions, but operators like
|
// these keywords should not appear inside expressions, but operators like
|
||||||
// 'typeof', 'instanceof', and 'in' are allowed
|
// 'typeof', 'instanceof', and 'in' are allowed
|
||||||
|
@ -13,7 +13,7 @@ const prohibitedKeywordRE = new RegExp(
|
||||||
)
|
)
|
||||||
.split(',')
|
.split(',')
|
||||||
.join('\\b|\\b') +
|
.join('\\b|\\b') +
|
||||||
'\\b'
|
'\\b',
|
||||||
)
|
)
|
||||||
|
|
||||||
// strip strings in expressions
|
// strip strings in expressions
|
||||||
|
@ -29,7 +29,7 @@ export function validateBrowserExpression(
|
||||||
node: SimpleExpressionNode,
|
node: SimpleExpressionNode,
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
asParams = false,
|
asParams = false,
|
||||||
asRawStatements = false
|
asRawStatements = false,
|
||||||
) {
|
) {
|
||||||
const exp = node.content
|
const exp = node.content
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ export function validateBrowserExpression(
|
||||||
new Function(
|
new Function(
|
||||||
asRawStatements
|
asRawStatements
|
||||||
? ` ${exp} `
|
? ` ${exp} `
|
||||||
: `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`
|
: `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`,
|
||||||
)
|
)
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
let message = e.message
|
let message = e.message
|
||||||
|
@ -58,8 +58,8 @@ export function validateBrowserExpression(
|
||||||
ErrorCodes.X_INVALID_EXPRESSION,
|
ErrorCodes.X_INVALID_EXPRESSION,
|
||||||
node.loc,
|
node.loc,
|
||||||
undefined,
|
undefined,
|
||||||
message
|
message,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,16 +29,16 @@ describe('decodeHtmlBrowser', () => {
|
||||||
|
|
||||||
// #3001 html tags inside attribute values
|
// #3001 html tags inside attribute values
|
||||||
expect(decodeHtmlBrowser('<strong>Text</strong>', true)).toBe(
|
expect(decodeHtmlBrowser('<strong>Text</strong>', true)).toBe(
|
||||||
'<strong>Text</strong>'
|
'<strong>Text</strong>',
|
||||||
)
|
)
|
||||||
expect(decodeHtmlBrowser('<strong>&</strong>', true)).toBe(
|
expect(decodeHtmlBrowser('<strong>&</strong>', true)).toBe(
|
||||||
'<strong>&</strong>'
|
'<strong>&</strong>',
|
||||||
)
|
)
|
||||||
expect(
|
expect(
|
||||||
decodeHtmlBrowser(
|
decodeHtmlBrowser(
|
||||||
'<strong><strong>&</strong></strong>',
|
'<strong><strong>&</strong></strong>',
|
||||||
true
|
true,
|
||||||
)
|
),
|
||||||
).toBe('<strong><strong>&</strong></strong>')
|
).toBe('<strong><strong>&</strong></strong>')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import {
|
import {
|
||||||
baseParse as parse,
|
type AttributeNode,
|
||||||
NodeTypes,
|
|
||||||
ElementNode,
|
|
||||||
TextNode,
|
|
||||||
ElementTypes,
|
|
||||||
InterpolationNode,
|
|
||||||
AttributeNode,
|
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
Namespaces
|
type ElementNode,
|
||||||
|
ElementTypes,
|
||||||
|
type InterpolationNode,
|
||||||
|
Namespaces,
|
||||||
|
NodeTypes,
|
||||||
|
type TextNode,
|
||||||
|
baseParse as parse,
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { parserOptions } from '../src/parserOptions'
|
import { parserOptions } from '../src/parserOptions'
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ describe('DOM parser', () => {
|
||||||
test('textarea handles comments/elements as just text', () => {
|
test('textarea handles comments/elements as just text', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<textarea>some<div>text</div>and<!--comment--></textarea>',
|
'<textarea>some<div>text</div>and<!--comment--></textarea>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const element = ast.children[0] as ElementNode
|
const element = ast.children[0] as ElementNode
|
||||||
const text = element.children[0] as TextNode
|
const text = element.children[0] as TextNode
|
||||||
|
@ -27,8 +27,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 10, line: 1, column: 11 },
|
start: { offset: 10, line: 1, column: 11 },
|
||||||
end: { offset: 46, line: 1, column: 47 },
|
end: { offset: 46, line: 1, column: 47 },
|
||||||
source: 'some<div>text</div>and<!--comment-->'
|
source: 'some<div>text</div>and<!--comment-->',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -43,8 +43,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 10, line: 1, column: 11 },
|
start: { offset: 10, line: 1, column: 11 },
|
||||||
end: { offset: 15, line: 1, column: 16 },
|
end: { offset: 15, line: 1, column: 16 },
|
||||||
source: '&'
|
source: '&',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -58,16 +58,16 @@ describe('DOM parser', () => {
|
||||||
content: {
|
content: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `foo`,
|
content: `foo`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
test('style handles comments/elements as just a text', () => {
|
test('style handles comments/elements as just a text', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<style>some<div>text</div>and<!--comment--></style>',
|
'<style>some<div>text</div>and<!--comment--></style>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const element = ast.children[0] as ElementNode
|
const element = ast.children[0] as ElementNode
|
||||||
const text = element.children[0] as TextNode
|
const text = element.children[0] as TextNode
|
||||||
|
@ -78,8 +78,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 7, line: 1, column: 8 },
|
start: { offset: 7, line: 1, column: 8 },
|
||||||
end: { offset: 43, line: 1, column: 44 },
|
end: { offset: 43, line: 1, column: 44 },
|
||||||
source: 'some<div>text</div>and<!--comment-->'
|
source: 'some<div>text</div>and<!--comment-->',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -94,8 +94,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 7, line: 1, column: 8 },
|
start: { offset: 7, line: 1, column: 8 },
|
||||||
end: { offset: 12, line: 1, column: 13 },
|
end: { offset: 12, line: 1, column: 13 },
|
||||||
source: '&'
|
source: '&',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -109,8 +109,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 14, line: 1, column: 15 },
|
start: { offset: 14, line: 1, column: 15 },
|
||||||
end: { offset: 23, line: 1, column: 24 },
|
end: { offset: 23, line: 1, column: 24 },
|
||||||
source: 'some text'
|
source: 'some text',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -120,21 +120,21 @@ describe('DOM parser', () => {
|
||||||
expect((ast.children[0] as ElementNode).children).toMatchObject([
|
expect((ast.children[0] as ElementNode).children).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: ` \na `
|
content: ` \na `,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `foo \n bar`
|
content: `foo \n bar`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: ` \n c`
|
content: ` \n c`,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ describe('DOM parser', () => {
|
||||||
expect((ast.children[0] as ElementNode).children).toMatchObject([
|
expect((ast.children[0] as ElementNode).children).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `hello`
|
content: `hello`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
|
@ -153,10 +153,10 @@ describe('DOM parser', () => {
|
||||||
{
|
{
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
// should not remove the leading newline for nested elements
|
// should not remove the leading newline for nested elements
|
||||||
content: `\nbye`
|
content: `\nbye`,
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -166,7 +166,7 @@ describe('DOM parser', () => {
|
||||||
const ast = parse(`foo bar`, parserOptions)
|
const ast = parse(`foo bar`, parserOptions)
|
||||||
expect(ast.children[0]).toMatchObject({
|
expect(ast.children[0]).toMatchObject({
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
content: `foo${nbsp}${nbsp}bar`
|
content: `foo${nbsp}${nbsp}bar`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -181,8 +181,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 0, line: 1, column: 1 },
|
start: { offset: 0, line: 1, column: 1 },
|
||||||
end: { offset: 11, line: 1, column: 12 },
|
end: { offset: 11, line: 1, column: 12 },
|
||||||
source: '&ersand;'
|
source: '&ersand;',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ describe('DOM parser', () => {
|
||||||
test('HTML entities compatibility in attribute', () => {
|
test('HTML entities compatibility in attribute', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<div a="&ersand;" b="&ersand;" c="&!"></div>',
|
'<div a="&ersand;" b="&ersand;" c="&!"></div>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const element = ast.children[0] as ElementNode
|
const element = ast.children[0] as ElementNode
|
||||||
const text1 = (element.props[0] as AttributeNode).value
|
const text1 = (element.props[0] as AttributeNode).value
|
||||||
|
@ -203,8 +203,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 7, line: 1, column: 8 },
|
start: { offset: 7, line: 1, column: 8 },
|
||||||
end: { offset: 20, line: 1, column: 21 },
|
end: { offset: 20, line: 1, column: 21 },
|
||||||
source: '"&ersand;"'
|
source: '"&ersand;"',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(text2).toStrictEqual({
|
expect(text2).toStrictEqual({
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
|
@ -212,8 +212,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 23, line: 1, column: 24 },
|
start: { offset: 23, line: 1, column: 24 },
|
||||||
end: { offset: 37, line: 1, column: 38 },
|
end: { offset: 37, line: 1, column: 38 },
|
||||||
source: '"&ersand;"'
|
source: '"&ersand;"',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(text3).toStrictEqual({
|
expect(text3).toStrictEqual({
|
||||||
type: NodeTypes.TEXT,
|
type: NodeTypes.TEXT,
|
||||||
|
@ -221,8 +221,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 40, line: 1, column: 41 },
|
start: { offset: 40, line: 1, column: 41 },
|
||||||
end: { offset: 47, line: 1, column: 48 },
|
end: { offset: 47, line: 1, column: 48 },
|
||||||
source: '"&!"'
|
source: '"&!"',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -236,8 +236,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 0, line: 1, column: 1 },
|
start: { offset: 0, line: 1, column: 1 },
|
||||||
end: { offset: 6, line: 1, column: 7 },
|
end: { offset: 6, line: 1, column: 7 },
|
||||||
source: '†'
|
source: '†',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -258,14 +258,14 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 8, line: 1, column: 9 },
|
start: { offset: 8, line: 1, column: 9 },
|
||||||
end: { offset: 16, line: 1, column: 17 },
|
end: { offset: 16, line: 1, column: 17 },
|
||||||
source: 'a < b'
|
source: 'a < b',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 5, line: 1, column: 6 },
|
start: { offset: 5, line: 1, column: 6 },
|
||||||
end: { offset: 19, line: 1, column: 20 },
|
end: { offset: 19, line: 1, column: 20 },
|
||||||
source: '{{ a < b }}'
|
source: '{{ a < b }}',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -285,9 +285,9 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 0, line: 1, column: 1 },
|
start: { offset: 0, line: 1, column: 1 },
|
||||||
end: { offset: 5, line: 1, column: 6 },
|
end: { offset: 5, line: 1, column: 6 },
|
||||||
source: '<img>'
|
source: '<img>',
|
||||||
},
|
},
|
||||||
codegenNode: undefined
|
codegenNode: undefined,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -297,26 +297,26 @@ describe('DOM parser', () => {
|
||||||
expect(ast.children[0]).toMatchObject({
|
expect(ast.children[0]).toMatchObject({
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: 'div',
|
tag: 'div',
|
||||||
tagType: ElementTypes.ELEMENT
|
tagType: ElementTypes.ELEMENT,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ast.children[1]).toMatchObject({
|
expect(ast.children[1]).toMatchObject({
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: 'comp',
|
tag: 'comp',
|
||||||
tagType: ElementTypes.COMPONENT
|
tagType: ElementTypes.COMPONENT,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(ast.children[2]).toMatchObject({
|
expect(ast.children[2]).toMatchObject({
|
||||||
type: NodeTypes.ELEMENT,
|
type: NodeTypes.ELEMENT,
|
||||||
tag: 'Comp',
|
tag: 'Comp',
|
||||||
tagType: ElementTypes.COMPONENT
|
tagType: ElementTypes.COMPONENT,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('Strict end tag detection for textarea.', () => {
|
test('Strict end tag detection for textarea.', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<textarea>hello</textarea</textarea0></texTArea>',
|
'<textarea>hello</textarea</textarea0></texTArea>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const element = ast.children[0] as ElementNode
|
const element = ast.children[0] as ElementNode
|
||||||
const text = element.children[0] as TextNode
|
const text = element.children[0] as TextNode
|
||||||
|
@ -328,8 +328,8 @@ describe('DOM parser', () => {
|
||||||
loc: {
|
loc: {
|
||||||
start: { offset: 10, line: 1, column: 11 },
|
start: { offset: 10, line: 1, column: 11 },
|
||||||
end: { offset: 37, line: 1, column: 38 },
|
end: { offset: 37, line: 1, column: 38 },
|
||||||
source: 'hello</textarea</textarea0>'
|
source: 'hello</textarea</textarea0>',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -359,7 +359,7 @@ describe('DOM parser', () => {
|
||||||
test('SVG in MATH_ML namespace', () => {
|
test('SVG in MATH_ML namespace', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<math><annotation-xml><svg></svg></annotation-xml></math>',
|
'<math><annotation-xml><svg></svg></annotation-xml></math>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const elementMath = ast.children[0] as ElementNode
|
const elementMath = ast.children[0] as ElementNode
|
||||||
const elementAnnotation = elementMath.children[0] as ElementNode
|
const elementAnnotation = elementMath.children[0] as ElementNode
|
||||||
|
@ -372,7 +372,7 @@ describe('DOM parser', () => {
|
||||||
test('html text/html in MATH_ML namespace', () => {
|
test('html text/html in MATH_ML namespace', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<math><annotation-xml encoding="text/html"><test/></annotation-xml></math>',
|
'<math><annotation-xml encoding="text/html"><test/></annotation-xml></math>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
|
|
||||||
const elementMath = ast.children[0] as ElementNode
|
const elementMath = ast.children[0] as ElementNode
|
||||||
|
@ -386,7 +386,7 @@ describe('DOM parser', () => {
|
||||||
test('html application/xhtml+xml in MATH_ML namespace', () => {
|
test('html application/xhtml+xml in MATH_ML namespace', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<math><annotation-xml encoding="application/xhtml+xml"><test/></annotation-xml></math>',
|
'<math><annotation-xml encoding="application/xhtml+xml"><test/></annotation-xml></math>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const elementMath = ast.children[0] as ElementNode
|
const elementMath = ast.children[0] as ElementNode
|
||||||
const elementAnnotation = elementMath.children[0] as ElementNode
|
const elementAnnotation = elementMath.children[0] as ElementNode
|
||||||
|
@ -399,7 +399,7 @@ describe('DOM parser', () => {
|
||||||
test('mtext malignmark in MATH_ML namespace', () => {
|
test('mtext malignmark in MATH_ML namespace', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<math><mtext><malignmark/></mtext></math>',
|
'<math><mtext><malignmark/></mtext></math>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const elementMath = ast.children[0] as ElementNode
|
const elementMath = ast.children[0] as ElementNode
|
||||||
const elementText = elementMath.children[0] as ElementNode
|
const elementText = elementMath.children[0] as ElementNode
|
||||||
|
@ -422,7 +422,7 @@ describe('DOM parser', () => {
|
||||||
test('foreignObject tag in SVG namespace', () => {
|
test('foreignObject tag in SVG namespace', () => {
|
||||||
const ast = parse(
|
const ast = parse(
|
||||||
'<svg><foreignObject><test/></foreignObject></svg>',
|
'<svg><foreignObject><test/></foreignObject></svg>',
|
||||||
parserOptions
|
parserOptions,
|
||||||
)
|
)
|
||||||
const elementSvg = ast.children[0] as ElementNode
|
const elementSvg = ast.children[0] as ElementNode
|
||||||
const elementForeignObject = elementSvg.children[0] as ElementNode
|
const elementForeignObject = elementSvg.children[0] as ElementNode
|
||||||
|
@ -473,7 +473,7 @@ describe('DOM parser', () => {
|
||||||
test('root ns', () => {
|
test('root ns', () => {
|
||||||
const ast = parse('<foreignObject><test/></foreignObject>', {
|
const ast = parse('<foreignObject><test/></foreignObject>', {
|
||||||
...parserOptions,
|
...parserOptions,
|
||||||
ns: Namespaces.SVG
|
ns: Namespaces.SVG,
|
||||||
})
|
})
|
||||||
const elementForieng = ast.children[0] as ElementNode
|
const elementForieng = ast.children[0] as ElementNode
|
||||||
const element = elementForieng.children[0] as ElementNode
|
const element = elementForieng.children[0] as ElementNode
|
||||||
|
@ -487,13 +487,13 @@ describe('DOM parser', () => {
|
||||||
// treatment for <script>, <style>, <textarea> etc.
|
// treatment for <script>, <style>, <textarea> etc.
|
||||||
const ast = parse('<script><g/><g/></script>', {
|
const ast = parse('<script><g/><g/></script>', {
|
||||||
...parserOptions,
|
...parserOptions,
|
||||||
ns: Namespaces.SVG
|
ns: Namespaces.SVG,
|
||||||
})
|
})
|
||||||
const elementSvg = ast.children[0] as ElementNode
|
const elementSvg = ast.children[0] as ElementNode
|
||||||
// should parse as nodes instead of text
|
// should parse as nodes instead of text
|
||||||
expect(elementSvg.children).toMatchObject([
|
expect(elementSvg.children).toMatchObject([
|
||||||
{ type: NodeTypes.ELEMENT, tag: 'g' },
|
{ type: NodeTypes.ELEMENT, tag: 'g' },
|
||||||
{ type: NodeTypes.ELEMENT, tag: 'g' }
|
{ type: NodeTypes.ELEMENT, tag: 'g' },
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe('Transition multi children warnings', () => {
|
||||||
function checkWarning(
|
function checkWarning(
|
||||||
template: string,
|
template: string,
|
||||||
shouldWarn: boolean,
|
shouldWarn: boolean,
|
||||||
message = `<Transition> expects exactly one child element or component.`
|
message = `<Transition> expects exactly one child element or component.`,
|
||||||
) {
|
) {
|
||||||
const spy = vi.fn()
|
const spy = vi.fn()
|
||||||
compile(template.trim(), {
|
compile(template.trim(), {
|
||||||
|
@ -12,7 +12,7 @@ describe('Transition multi children warnings', () => {
|
||||||
transformHoist: null,
|
transformHoist: null,
|
||||||
onError: err => {
|
onError: err => {
|
||||||
spy(err.message)
|
spy(err.message)
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (shouldWarn) expect(spy).toHaveBeenCalledWith(message)
|
if (shouldWarn) expect(spy).toHaveBeenCalledWith(message)
|
||||||
|
@ -27,7 +27,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div>hey</div>
|
<div>hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div v-for="i in items">hey</div>
|
<div v-for="i in items">hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -50,7 +50,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div v-else v-for="i in items">hey</div>
|
<div v-else v-for="i in items">hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<template v-if="ok"></template>
|
<template v-if="ok"></template>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -73,7 +73,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<template v-else></template>
|
<template v-else></template>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div v-if="other">hey</div>
|
<div v-if="other">hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -96,7 +96,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div>hey</div>
|
<div>hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div v-if="a">hey</div>
|
<div v-if="a">hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div v-else>hey</div>
|
<div v-else>hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ describe('Transition multi children warnings', () => {
|
||||||
<div v-else>hey</div>
|
<div v-else>hey</div>
|
||||||
</transition>
|
</transition>
|
||||||
`,
|
`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -143,7 +143,7 @@ test('inject persisted when child has v-show', () => {
|
||||||
<transition>
|
<transition>
|
||||||
<div v-show="ok" />
|
<div v-show="ok" />
|
||||||
</transition>
|
</transition>
|
||||||
`).code
|
`).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -161,6 +161,6 @@ test('the v-if/else-if/else branches in Transition should ignore comments', () =
|
||||||
<p v-else/>
|
<p v-else/>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
`).code
|
`).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { compile, CompilerError } from '../../src'
|
import { type CompilerError, compile } from '../../src'
|
||||||
|
|
||||||
describe('compiler: ignore side effect tags', () => {
|
describe('compiler: ignore side effect tags', () => {
|
||||||
it('should ignore script', () => {
|
it('should ignore script', () => {
|
||||||
|
@ -6,7 +6,7 @@ describe('compiler: ignore side effect tags', () => {
|
||||||
const { code } = compile(`<script>console.log(1)</script>`, {
|
const { code } = compile(`<script>console.log(1)</script>`, {
|
||||||
onError(e) {
|
onError(e) {
|
||||||
err = e
|
err = e
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(code).not.toMatch('script')
|
expect(code).not.toMatch('script')
|
||||||
expect(err).toBeDefined()
|
expect(err).toBeDefined()
|
||||||
|
@ -18,7 +18,7 @@ describe('compiler: ignore side effect tags', () => {
|
||||||
const { code } = compile(`<style>h1 { color: red }</style>`, {
|
const { code } = compile(`<style>h1 { color: red }</style>`, {
|
||||||
onError(e) {
|
onError(e) {
|
||||||
err = e
|
err = e
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(code).not.toMatch('style')
|
expect(code).not.toMatch('style')
|
||||||
expect(err).toBeDefined()
|
expect(err).toBeDefined()
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import {
|
import {
|
||||||
compile,
|
|
||||||
NodeTypes,
|
|
||||||
CREATE_STATIC,
|
CREATE_STATIC,
|
||||||
|
ConstantTypes,
|
||||||
|
NodeTypes,
|
||||||
|
compile,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
ConstantTypes
|
|
||||||
} from '../../src'
|
} from '../../src'
|
||||||
import {
|
import {
|
||||||
|
StringifyThresholds,
|
||||||
stringifyStatic,
|
stringifyStatic,
|
||||||
StringifyThresholds
|
|
||||||
} from '../../src/transforms/stringifyStatic'
|
} from '../../src/transforms/stringifyStatic'
|
||||||
|
|
||||||
describe('stringify static html', () => {
|
describe('stringify static html', () => {
|
||||||
|
@ -15,7 +15,7 @@ describe('stringify static html', () => {
|
||||||
return compile(template, {
|
return compile(template, {
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
transformHoist: stringifyStatic
|
transformHoist: stringifyStatic,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ describe('stringify static html', () => {
|
||||||
|
|
||||||
test('should bail on non-eligible static trees', () => {
|
test('should bail on non-eligible static trees', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div><div><div>hello</div><div>hello</div></div></div>`
|
`<div><div><div>hello</div><div>hello</div></div></div>`,
|
||||||
)
|
)
|
||||||
// should be a normal vnode call
|
// should be a normal vnode call
|
||||||
expect(ast.hoists[0]!.type).toBe(NodeTypes.VNODE_CALL)
|
expect(ast.hoists[0]!.type).toBe(NodeTypes.VNODE_CALL)
|
||||||
|
@ -35,8 +35,8 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div><div>${repeat(
|
`<div><div>${repeat(
|
||||||
`<span class="foo"/>`,
|
`<span class="foo"/>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div></div>`
|
)}</div></div>`,
|
||||||
)
|
)
|
||||||
// should be optimized now
|
// should be optimized now
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
|
@ -47,15 +47,15 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
`<div>${repeat(
|
`<div>${repeat(
|
||||||
`<span class="foo"></span>`,
|
`<span class="foo"></span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div>`
|
)}</div>`,
|
||||||
),
|
),
|
||||||
'1'
|
'1',
|
||||||
]
|
],
|
||||||
}, // the children array is hoisted as well
|
}, // the children array is hoisted as well
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -63,8 +63,8 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div><div>${repeat(
|
`<div><div>${repeat(
|
||||||
`<span/>`,
|
`<span/>`,
|
||||||
StringifyThresholds.NODE_COUNT
|
StringifyThresholds.NODE_COUNT,
|
||||||
)}</div></div>`
|
)}</div></div>`,
|
||||||
)
|
)
|
||||||
// should be optimized now
|
// should be optimized now
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
|
@ -75,16 +75,16 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
`<div>${repeat(
|
`<div>${repeat(
|
||||||
`<span></span>`,
|
`<span></span>`,
|
||||||
StringifyThresholds.NODE_COUNT
|
StringifyThresholds.NODE_COUNT,
|
||||||
)}</div>`
|
)}</div>`,
|
||||||
),
|
),
|
||||||
'1'
|
'1',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
// the children array is hoisted as well
|
// the children array is hoisted as well
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -92,8 +92,8 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div>${repeat(
|
`<div>${repeat(
|
||||||
`<span class="foo"/>`,
|
`<span class="foo"/>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div>`
|
)}</div>`,
|
||||||
)
|
)
|
||||||
// should have 6 hoisted nodes (including the entire array),
|
// should have 6 hoisted nodes (including the entire array),
|
||||||
// but 2~5 should be null because they are merged into 1
|
// but 2~5 should be null because they are merged into 1
|
||||||
|
@ -105,19 +105,19 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
repeat(
|
repeat(
|
||||||
`<span class="foo"></span>`,
|
`<span class="foo"></span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)
|
|
||||||
),
|
),
|
||||||
'5'
|
),
|
||||||
]
|
'5',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -125,8 +125,8 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div><div :style="{ color: 'red' }">${repeat(
|
`<div><div :style="{ color: 'red' }">${repeat(
|
||||||
`<span :class="[{ foo: true }, { bar: true }]">{{ 1 }} + {{ false }}</span>`,
|
`<span :class="[{ foo: true }, { bar: true }]">{{ 1 }} + {{ false }}</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div></div>`
|
)}</div></div>`,
|
||||||
)
|
)
|
||||||
// should be optimized now
|
// should be optimized now
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
|
@ -137,15 +137,15 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
`<div style="color:red;">${repeat(
|
`<div style="color:red;">${repeat(
|
||||||
`<span class="foo bar">1 + false</span>`,
|
`<span class="foo bar">1 + false</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div>`
|
)}</div>`,
|
||||||
),
|
),
|
||||||
'1'
|
'1',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -154,8 +154,8 @@ describe('stringify static html', () => {
|
||||||
`<div><div>${repeat(
|
`<div><div>${repeat(
|
||||||
`<span :class="'foo' + '>ar'">{{ 1 }} + {{ '<' }}</span>` +
|
`<span :class="'foo' + '>ar'">{{ 1 }} + {{ '<' }}</span>` +
|
||||||
`<span>&</span>`,
|
`<span>&</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div></div>`
|
)}</div></div>`,
|
||||||
)
|
)
|
||||||
// should be optimized now
|
// should be optimized now
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
|
@ -166,15 +166,15 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
`<div>${repeat(
|
`<div>${repeat(
|
||||||
`<span class="foo>ar">1 + <</span>` + `<span>&</span>`,
|
`<span class="foo>ar">1 + <</span>` + `<span>&</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div>`
|
)}</div>`,
|
||||||
),
|
),
|
||||||
'1'
|
'1',
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -182,7 +182,7 @@ describe('stringify static html', () => {
|
||||||
const { ast, code } = compile(
|
const { ast, code } = compile(
|
||||||
`<div><div>${repeat(
|
`<div><div>${repeat(
|
||||||
`<span class="foo">foo</span>`,
|
`<span class="foo">foo</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}<img src="./foo" /></div></div>`,
|
)}<img src="./foo" /></div></div>`,
|
||||||
{
|
{
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
|
@ -195,7 +195,7 @@ describe('stringify static html', () => {
|
||||||
'_imports_0_',
|
'_imports_0_',
|
||||||
false,
|
false,
|
||||||
node.loc,
|
node.loc,
|
||||||
ConstantTypes.CAN_HOIST
|
ConstantTypes.CAN_HOIST,
|
||||||
)
|
)
|
||||||
node.props[0] = {
|
node.props[0] = {
|
||||||
type: NodeTypes.DIRECTIVE,
|
type: NodeTypes.DIRECTIVE,
|
||||||
|
@ -203,23 +203,23 @@ describe('stringify static html', () => {
|
||||||
arg: createSimpleExpression('src', true),
|
arg: createSimpleExpression('src', true),
|
||||||
exp,
|
exp,
|
||||||
modifiers: [],
|
modifiers: [],
|
||||||
loc: node.loc
|
loc: node.loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
// the expression and the tree are still hoistable
|
// the expression and the tree are still hoistable
|
||||||
// but should stay NodeTypes.VNODE_CALL
|
// but should stay NodeTypes.VNODE_CALL
|
||||||
// if it's stringified it will be NodeTypes.JS_CALL_EXPRESSION
|
// if it's stringified it will be NodeTypes.JS_CALL_EXPRESSION
|
||||||
type: NodeTypes.VNODE_CALL
|
type: NodeTypes.VNODE_CALL,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -230,7 +230,7 @@ describe('stringify static html', () => {
|
||||||
const { ast, code } = compile(
|
const { ast, code } = compile(
|
||||||
`<div><div>${repeat(
|
`<div><div>${repeat(
|
||||||
`<span class="foo">foo</span>`,
|
`<span class="foo">foo</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}<img src="./foo" /></div></div>`,
|
)}<img src="./foo" /></div></div>`,
|
||||||
{
|
{
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
|
@ -243,7 +243,7 @@ describe('stringify static html', () => {
|
||||||
'_imports_0_',
|
'_imports_0_',
|
||||||
false,
|
false,
|
||||||
node.loc,
|
node.loc,
|
||||||
ConstantTypes.CAN_STRINGIFY
|
ConstantTypes.CAN_STRINGIFY,
|
||||||
)
|
)
|
||||||
node.props[0] = {
|
node.props[0] = {
|
||||||
type: NodeTypes.DIRECTIVE,
|
type: NodeTypes.DIRECTIVE,
|
||||||
|
@ -251,22 +251,22 @@ describe('stringify static html', () => {
|
||||||
arg: createSimpleExpression('src', true),
|
arg: createSimpleExpression('src', true),
|
||||||
exp,
|
exp,
|
||||||
modifiers: [],
|
modifiers: [],
|
||||||
loc: node.loc
|
loc: node.loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
// the hoisted node should be NodeTypes.JS_CALL_EXPRESSION
|
// the hoisted node should be NodeTypes.JS_CALL_EXPRESSION
|
||||||
// of `createStaticVNode()` instead of dynamic NodeTypes.VNODE_CALL
|
// of `createStaticVNode()` instead of dynamic NodeTypes.VNODE_CALL
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -276,31 +276,31 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div><div><input indeterminate>${repeat(
|
`<div><div><input indeterminate>${repeat(
|
||||||
`<span class="foo">foo</span>`,
|
`<span class="foo">foo</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div></div>`
|
)}</div></div>`,
|
||||||
)
|
)
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const { ast: ast2 } = compileWithStringify(
|
const { ast: ast2 } = compileWithStringify(
|
||||||
`<div><div><input :indeterminate="true">${repeat(
|
`<div><div><input :indeterminate="true">${repeat(
|
||||||
`<span class="foo">foo</span>`,
|
`<span class="foo">foo</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div></div>`
|
)}</div></div>`,
|
||||||
)
|
)
|
||||||
expect(ast2.hoists).toMatchObject([
|
expect(ast2.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -308,31 +308,31 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div><div>${repeat(
|
`<div><div>${repeat(
|
||||||
`<span class="foo">foo</span>`,
|
`<span class="foo">foo</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}<input indeterminate></div></div>`
|
)}<input indeterminate></div></div>`,
|
||||||
)
|
)
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
const { ast: ast2 } = compileWithStringify(
|
const { ast: ast2 } = compileWithStringify(
|
||||||
`<div><div>${repeat(
|
`<div><div>${repeat(
|
||||||
`<span class="foo">foo</span>`,
|
`<span class="foo">foo</span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}<input :indeterminate="true"></div></div>`
|
)}<input :indeterminate="true"></div></div>`,
|
||||||
)
|
)
|
||||||
expect(ast2.hoists).toMatchObject([
|
expect(ast2.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -340,16 +340,16 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<table><tbody>${repeat(
|
`<table><tbody>${repeat(
|
||||||
`<tr class="foo"><td>foo</td></tr>`,
|
`<tr class="foo"><td>foo</td></tr>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</tbody></table>`
|
)}</tbody></table>`,
|
||||||
)
|
)
|
||||||
expect(ast.hoists).toMatchObject([
|
expect(ast.hoists).toMatchObject([
|
||||||
{
|
{
|
||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||||
}
|
},
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -357,30 +357,30 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<foo>${repeat(
|
`<foo>${repeat(
|
||||||
`<div class="foo"></div>`,
|
`<div class="foo"></div>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</foo>`
|
)}</foo>`,
|
||||||
)
|
)
|
||||||
expect(ast.hoists.length).toBe(
|
expect(ast.hoists.length).toBe(
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)
|
)
|
||||||
ast.hoists.forEach(node => {
|
ast.hoists.forEach(node => {
|
||||||
expect(node).toMatchObject({
|
expect(node).toMatchObject({
|
||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
const { ast: ast2 } = compileWithStringify(
|
const { ast: ast2 } = compileWithStringify(
|
||||||
`<foo><template #foo>${repeat(
|
`<foo><template #foo>${repeat(
|
||||||
`<div class="foo"></div>`,
|
`<div class="foo"></div>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</template></foo>`
|
)}</template></foo>`,
|
||||||
)
|
)
|
||||||
expect(ast2.hoists.length).toBe(
|
expect(ast2.hoists.length).toBe(
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)
|
)
|
||||||
ast2.hoists.forEach(node => {
|
ast2.hoists.forEach(node => {
|
||||||
expect(node).toMatchObject({
|
expect(node).toMatchObject({
|
||||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -389,8 +389,8 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div>${repeat(
|
`<div>${repeat(
|
||||||
`<span :title="null"></span>`,
|
`<span :title="null"></span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</div>`
|
)}</div>`,
|
||||||
)
|
)
|
||||||
expect(ast.hoists[0]).toMatchObject({
|
expect(ast.hoists[0]).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
@ -399,11 +399,11 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
`${repeat(
|
`${repeat(
|
||||||
`<span></span>`,
|
`<span></span>`,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}`
|
)}`,
|
||||||
),
|
),
|
||||||
'5'
|
'5',
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -412,8 +412,8 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<button :disabled="false">enable</button>${repeat(
|
`<button :disabled="false">enable</button>${repeat(
|
||||||
`<div></div>`,
|
`<div></div>`,
|
||||||
StringifyThresholds.NODE_COUNT
|
StringifyThresholds.NODE_COUNT,
|
||||||
)}`
|
)}`,
|
||||||
)
|
)
|
||||||
expect(ast.hoists[0]).toMatchObject({
|
expect(ast.hoists[0]).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
@ -422,11 +422,11 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
`<button>enable</button>${repeat(
|
`<button>enable</button>${repeat(
|
||||||
`<div></div>`,
|
`<div></div>`,
|
||||||
StringifyThresholds.NODE_COUNT
|
StringifyThresholds.NODE_COUNT,
|
||||||
)}`
|
)}`,
|
||||||
),
|
),
|
||||||
'21'
|
'21',
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -436,8 +436,8 @@ describe('stringify static html', () => {
|
||||||
const { ast } = compileWithStringify(
|
const { ast } = compileWithStringify(
|
||||||
`<div>${svg}${repeat(
|
`<div>${svg}${repeat(
|
||||||
repeated,
|
repeated,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</svg></div>`
|
)}</svg></div>`,
|
||||||
)
|
)
|
||||||
expect(ast.hoists[0]).toMatchObject({
|
expect(ast.hoists[0]).toMatchObject({
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
|
@ -446,11 +446,11 @@ describe('stringify static html', () => {
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
`${svg}${repeat(
|
`${svg}${repeat(
|
||||||
repeated,
|
repeated,
|
||||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||||
)}</svg>`
|
)}</svg>`,
|
||||||
),
|
),
|
||||||
'1'
|
'1',
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import {
|
import {
|
||||||
|
type CompilerOptions,
|
||||||
|
type ElementNode,
|
||||||
|
NodeTypes,
|
||||||
|
type VNodeCall,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
CompilerOptions,
|
|
||||||
ElementNode,
|
|
||||||
NodeTypes,
|
|
||||||
VNodeCall
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { transformBind } from '../../../compiler-core/src/transforms/vBind'
|
import { transformBind } from '../../../compiler-core/src/transforms/vBind'
|
||||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||||
|
@ -12,16 +12,16 @@ import { transformStyle } from '../../src/transforms/transformStyle'
|
||||||
|
|
||||||
function transformWithStyleTransform(
|
function transformWithStyleTransform(
|
||||||
template: string,
|
template: string,
|
||||||
options: CompilerOptions = {}
|
options: CompilerOptions = {},
|
||||||
) {
|
) {
|
||||||
const ast = parse(template)
|
const ast = parse(template)
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformStyle],
|
nodeTransforms: [transformStyle],
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return {
|
return {
|
||||||
root: ast,
|
root: ast,
|
||||||
node: ast.children[0] as ElementNode
|
node: ast.children[0] as ElementNode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,13 +34,13 @@ describe('compiler: style transform', () => {
|
||||||
arg: {
|
arg: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `style`,
|
content: `style`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
exp: {
|
exp: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `{"color":"red"}`,
|
content: `{"color":"red"}`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ describe('compiler: style transform', () => {
|
||||||
const { node } = transformWithStyleTransform(`<div style="color: red"/>`, {
|
const { node } = transformWithStyleTransform(`<div style="color: red"/>`, {
|
||||||
nodeTransforms: [transformStyle, transformElement],
|
nodeTransforms: [transformStyle, transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||||
|
@ -58,15 +58,15 @@ describe('compiler: style transform', () => {
|
||||||
key: {
|
key: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `style`,
|
content: `style`,
|
||||||
isStatic: true
|
isStatic: true,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `{"color":"red"}`,
|
content: `{"color":"red"}`,
|
||||||
isStatic: false
|
isStatic: false,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
// should not cause the STYLE patchFlag to be attached
|
// should not cause the STYLE patchFlag to be attached
|
||||||
expect((node.codegenNode as VNodeCall).patchFlag).toBeUndefined()
|
expect((node.codegenNode as VNodeCall).patchFlag).toBeUndefined()
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
|
type CompilerOptions,
|
||||||
|
type PlainElementNode,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
PlainElementNode,
|
|
||||||
CompilerOptions
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { transformVHtml } from '../../src/transforms/vHtml'
|
import { transformVHtml } from '../../src/transforms/vHtml'
|
||||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||||
import {
|
import {
|
||||||
createObjectMatcher,
|
createObjectMatcher,
|
||||||
genFlagText
|
genFlagText,
|
||||||
} from '../../../compiler-core/__tests__/testUtils'
|
} from '../../../compiler-core/__tests__/testUtils'
|
||||||
import { PatchFlags } from '@vue/shared'
|
import { PatchFlags } from '@vue/shared'
|
||||||
import { DOMErrorCodes } from '../../src/errors'
|
import { DOMErrorCodes } from '../../src/errors'
|
||||||
|
@ -18,9 +18,9 @@ function transformWithVHtml(template: string, options: CompilerOptions = {}) {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformElement],
|
nodeTransforms: [transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
html: transformVHtml
|
html: transformVHtml,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -31,40 +31,40 @@ describe('compiler: v-html transform', () => {
|
||||||
expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
innerHTML: `[test]`
|
innerHTML: `[test]`,
|
||||||
}),
|
}),
|
||||||
children: undefined,
|
children: undefined,
|
||||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||||
dynamicProps: `["innerHTML"]`
|
dynamicProps: `["innerHTML"]`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should raise error and ignore children when v-html is present', () => {
|
it('should raise error and ignore children when v-html is present', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
const ast = transformWithVHtml(`<div v-html="test">hello</div>`, {
|
const ast = transformWithVHtml(`<div v-html="test">hello</div>`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError.mock.calls).toMatchObject([
|
expect(onError.mock.calls).toMatchObject([
|
||||||
[{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }]
|
[{ code: DOMErrorCodes.X_V_HTML_WITH_CHILDREN }],
|
||||||
])
|
])
|
||||||
expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
innerHTML: `[test]`
|
innerHTML: `[test]`,
|
||||||
}),
|
}),
|
||||||
children: undefined, // <-- children should have been removed
|
children: undefined, // <-- children should have been removed
|
||||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||||
dynamicProps: `["innerHTML"]`
|
dynamicProps: `["innerHTML"]`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should raise error if has no expression', () => {
|
it('should raise error if has no expression', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
transformWithVHtml(`<div v-html></div>`, {
|
transformWithVHtml(`<div v-html></div>`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError.mock.calls).toMatchObject([
|
expect(onError.mock.calls).toMatchObject([
|
||||||
[{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }]
|
[{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }],
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {
|
import {
|
||||||
|
type CompilerOptions,
|
||||||
|
generate,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
CompilerOptions,
|
|
||||||
generate
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { transformModel } from '../../src/transforms/vModel'
|
import { transformModel } from '../../src/transforms/vModel'
|
||||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||||
|
@ -12,7 +12,7 @@ import {
|
||||||
V_MODEL_DYNAMIC,
|
V_MODEL_DYNAMIC,
|
||||||
V_MODEL_RADIO,
|
V_MODEL_RADIO,
|
||||||
V_MODEL_SELECT,
|
V_MODEL_SELECT,
|
||||||
V_MODEL_TEXT
|
V_MODEL_TEXT,
|
||||||
} from '../../src/runtimeHelpers'
|
} from '../../src/runtimeHelpers'
|
||||||
|
|
||||||
function transformWithModel(template: string, options: CompilerOptions = {}) {
|
function transformWithModel(template: string, options: CompilerOptions = {}) {
|
||||||
|
@ -20,9 +20,9 @@ function transformWithModel(template: string, options: CompilerOptions = {}) {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformElement],
|
nodeTransforms: [transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
model: transformModel
|
model: transformModel,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -70,7 +70,7 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(generate(root).code).toMatchSnapshot()
|
expect(generate(root).code).toMatchSnapshot()
|
||||||
|
|
||||||
const root2 = transformWithModel(
|
const root2 = transformWithModel(
|
||||||
'<input v-bind:[key]="val" v-model="model" />'
|
'<input v-bind:[key]="val" v-model="model" />',
|
||||||
)
|
)
|
||||||
expect(root2.helpers).toContain(V_MODEL_DYNAMIC)
|
expect(root2.helpers).toContain(V_MODEL_DYNAMIC)
|
||||||
expect(generate(root2).code).toMatchSnapshot()
|
expect(generate(root2).code).toMatchSnapshot()
|
||||||
|
@ -98,8 +98,8 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT
|
code: DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -110,8 +110,8 @@ describe('compiler: transform v-model', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT
|
code: DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ describe('compiler: transform v-model', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
const root = transformWithModel('<my-input v-model="model" />', {
|
const root = transformWithModel('<my-input v-model="model" />', {
|
||||||
onError,
|
onError,
|
||||||
isCustomElement: tag => tag.startsWith('my-')
|
isCustomElement: tag => tag.startsWith('my-'),
|
||||||
})
|
})
|
||||||
expect(root.helpers).toContain(V_MODEL_TEXT)
|
expect(root.helpers).toContain(V_MODEL_TEXT)
|
||||||
expect(onError).not.toHaveBeenCalled()
|
expect(onError).not.toHaveBeenCalled()
|
||||||
|
@ -129,24 +129,24 @@ describe('compiler: transform v-model', () => {
|
||||||
test('should raise error if used file input element', () => {
|
test('should raise error if used file input element', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
transformWithModel(`<input type="file" v-model="test"/>`, {
|
transformWithModel(`<input type="file" v-model="test"/>`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT
|
code: DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should error on dynamic value binding alongside v-model', () => {
|
test('should error on dynamic value binding alongside v-model', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
transformWithModel(`<input v-model="test" :value="test" />`, {
|
transformWithModel(`<input v-model="test" :value="test" />`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE
|
code: DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -154,7 +154,7 @@ describe('compiler: transform v-model', () => {
|
||||||
test('should NOT error on static value binding alongside v-model', () => {
|
test('should NOT error on static value binding alongside v-model', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
transformWithModel(`<input v-model="test" value="test" />`, {
|
transformWithModel(`<input v-model="test" value="test" />`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError).not.toHaveBeenCalled()
|
expect(onError).not.toHaveBeenCalled()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
baseParse as parse,
|
BindingTypes,
|
||||||
CompilerOptions,
|
type CompilerOptions,
|
||||||
ElementNode,
|
type ElementNode,
|
||||||
TO_HANDLER_KEY,
|
|
||||||
helperNameMap,
|
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
ObjectExpression,
|
type ObjectExpression,
|
||||||
|
TO_HANDLER_KEY,
|
||||||
|
type VNodeCall,
|
||||||
|
helperNameMap,
|
||||||
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
VNodeCall,
|
|
||||||
BindingTypes
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { transformOn } from '../../src/transforms/vOn'
|
import { transformOn } from '../../src/transforms/vOn'
|
||||||
import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers'
|
import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers'
|
||||||
|
@ -22,31 +22,31 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformExpression, transformElement],
|
nodeTransforms: [transformExpression, transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
on: transformOn
|
on: transformOn,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
const node = (ast.children[0] as ElementNode).codegenNode as VNodeCall
|
const node = (ast.children[0] as ElementNode).codegenNode as VNodeCall
|
||||||
return {
|
return {
|
||||||
root: ast,
|
root: ast,
|
||||||
node,
|
node,
|
||||||
props: (node.props as ObjectExpression).properties
|
props: (node.props as ObjectExpression).properties,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
describe('compiler-dom: transform v-on', () => {
|
describe('compiler-dom: transform v-on', () => {
|
||||||
it('should support multiple modifiers w/ prefixIdentifiers: true', () => {
|
it('should support multiple modifiers w/ prefixIdentifiers: true', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @click.stop.prevent="test"/>`, {
|
} = parseWithVOn(`<div @click.stop.prevent="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_MODIFIERS,
|
callee: V_ON_WITH_MODIFIERS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["stop","prevent"]']
|
arguments: [{ content: '_ctx.test' }, '["stop","prevent"]'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -54,8 +54,8 @@ describe('compiler-dom: transform v-on', () => {
|
||||||
const { props } = parseWithVOn(
|
const { props } = parseWithVOn(
|
||||||
`<div @click.stop="test" @keyup.enter="test" />`,
|
`<div @click.stop="test" @keyup.enter="test" />`,
|
||||||
{
|
{
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
const [clickProp, keyUpProp] = props
|
const [clickProp, keyUpProp] = props
|
||||||
|
|
||||||
|
@ -64,95 +64,95 @@ describe('compiler-dom: transform v-on', () => {
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_MODIFIERS,
|
callee: V_ON_WITH_MODIFIERS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["stop"]']
|
arguments: [{ content: '_ctx.test' }, '["stop"]'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(keyUpProp).toMatchObject({
|
expect(keyUpProp).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_KEYS,
|
callee: V_ON_WITH_KEYS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["enter"]']
|
arguments: [{ content: '_ctx.test' }, '["enter"]'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should support multiple modifiers and event options w/ prefixIdentifiers: true', () => {
|
it('should support multiple modifiers and event options w/ prefixIdentifiers: true', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @click.stop.capture.once="test"/>`, {
|
} = parseWithVOn(`<div @click.stop.capture.once="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
key: {
|
key: {
|
||||||
content: `onClickCaptureOnce`
|
content: `onClickCaptureOnce`,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_MODIFIERS,
|
callee: V_ON_WITH_MODIFIERS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["stop"]']
|
arguments: [{ content: '_ctx.test' }, '["stop"]'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should wrap keys guard for keyboard events or dynamic events', () => {
|
it('should wrap keys guard for keyboard events or dynamic events', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @keydown.stop.capture.ctrl.a="test"/>`, {
|
} = parseWithVOn(`<div @keydown.stop.capture.ctrl.a="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
key: {
|
key: {
|
||||||
content: `onKeydownCapture`
|
content: `onKeydownCapture`,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_KEYS,
|
callee: V_ON_WITH_KEYS,
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
callee: V_ON_WITH_MODIFIERS,
|
callee: V_ON_WITH_MODIFIERS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["stop","ctrl"]']
|
arguments: [{ content: '_ctx.test' }, '["stop","ctrl"]'],
|
||||||
|
},
|
||||||
|
'["a"]',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
'["a"]'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not wrap keys guard if no key modifier is present', () => {
|
it('should not wrap keys guard if no key modifier is present', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @keyup.exact="test"/>`, {
|
} = parseWithVOn(`<div @keyup.exact="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_MODIFIERS,
|
callee: V_ON_WITH_MODIFIERS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["exact"]']
|
arguments: [{ content: '_ctx.test' }, '["exact"]'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should wrap keys guard for static key event w/ left/right modifiers', () => {
|
it('should wrap keys guard for static key event w/ left/right modifiers', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @keyup.left="test"/>`, {
|
} = parseWithVOn(`<div @keyup.left="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_KEYS,
|
callee: V_ON_WITH_KEYS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["left"]']
|
arguments: [{ content: '_ctx.test' }, '["left"]'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should wrap both for dynamic key event w/ left/right modifiers', () => {
|
it('should wrap both for dynamic key event w/ left/right modifiers', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @[e].left="test"/>`, {
|
} = parseWithVOn(`<div @[e].left="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
|
@ -161,41 +161,41 @@ describe('compiler-dom: transform v-on', () => {
|
||||||
arguments: [
|
arguments: [
|
||||||
{
|
{
|
||||||
callee: V_ON_WITH_MODIFIERS,
|
callee: V_ON_WITH_MODIFIERS,
|
||||||
arguments: [{ content: `_ctx.test` }, `["left"]`]
|
arguments: [{ content: `_ctx.test` }, `["left"]`],
|
||||||
|
},
|
||||||
|
'["left"]',
|
||||||
|
],
|
||||||
},
|
},
|
||||||
'["left"]'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should not wrap normal guard if there is only keys guard', () => {
|
it('should not wrap normal guard if there is only keys guard', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @keyup.enter="test"/>`, {
|
} = parseWithVOn(`<div @keyup.enter="test"/>`, {
|
||||||
prefixIdentifiers: true
|
prefixIdentifiers: true,
|
||||||
})
|
})
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
type: NodeTypes.JS_PROPERTY,
|
type: NodeTypes.JS_PROPERTY,
|
||||||
value: {
|
value: {
|
||||||
callee: V_ON_WITH_KEYS,
|
callee: V_ON_WITH_KEYS,
|
||||||
arguments: [{ content: '_ctx.test' }, '["enter"]']
|
arguments: [{ content: '_ctx.test' }, '["enter"]'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should transform click.right', () => {
|
test('should transform click.right', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @click.right="test"/>`)
|
} = parseWithVOn(`<div @click.right="test"/>`)
|
||||||
expect(prop.key).toMatchObject({
|
expect(prop.key).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `onContextmenu`
|
content: `onContextmenu`,
|
||||||
})
|
})
|
||||||
|
|
||||||
// dynamic
|
// dynamic
|
||||||
const {
|
const {
|
||||||
props: [prop2]
|
props: [prop2],
|
||||||
} = parseWithVOn(`<div @[event].right="test"/>`)
|
} = parseWithVOn(`<div @[event].right="test"/>`)
|
||||||
// (_toHandlerKey(event)).toLowerCase() === "onclick" ? "onContextmenu" : (_toHandlerKey(event))
|
// (_toHandlerKey(event)).toLowerCase() === "onclick" ? "onContextmenu" : (_toHandlerKey(event))
|
||||||
expect(prop2.key).toMatchObject({
|
expect(prop2.key).toMatchObject({
|
||||||
|
@ -206,34 +206,34 @@ describe('compiler-dom: transform v-on', () => {
|
||||||
children: [
|
children: [
|
||||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||||
{ content: 'event' },
|
{ content: 'event' },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
`) === "onClick" ? "onContextmenu" : (`,
|
`) === "onClick" ? "onContextmenu" : (`,
|
||||||
{
|
{
|
||||||
children: [
|
children: [
|
||||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||||
{ content: 'event' },
|
{ content: 'event' },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should transform click.middle', () => {
|
test('should transform click.middle', () => {
|
||||||
const {
|
const {
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @click.middle="test"/>`)
|
} = parseWithVOn(`<div @click.middle="test"/>`)
|
||||||
expect(prop.key).toMatchObject({
|
expect(prop.key).toMatchObject({
|
||||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||||
content: `onMouseup`
|
content: `onMouseup`,
|
||||||
})
|
})
|
||||||
|
|
||||||
// dynamic
|
// dynamic
|
||||||
const {
|
const {
|
||||||
props: [prop2]
|
props: [prop2],
|
||||||
} = parseWithVOn(`<div @[event].middle="test"/>`)
|
} = parseWithVOn(`<div @[event].middle="test"/>`)
|
||||||
// (_eventNaming(event)).toLowerCase() === "onclick" ? "onMouseup" : (_eventNaming(event))
|
// (_eventNaming(event)).toLowerCase() === "onclick" ? "onMouseup" : (_eventNaming(event))
|
||||||
expect(prop2.key).toMatchObject({
|
expect(prop2.key).toMatchObject({
|
||||||
|
@ -244,48 +244,48 @@ describe('compiler-dom: transform v-on', () => {
|
||||||
children: [
|
children: [
|
||||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||||
{ content: 'event' },
|
{ content: 'event' },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
`) === "onClick" ? "onMouseup" : (`,
|
`) === "onClick" ? "onMouseup" : (`,
|
||||||
{
|
{
|
||||||
children: [
|
children: [
|
||||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||||
{ content: 'event' },
|
{ content: 'event' },
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
`)`
|
`)`,
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('cache handler w/ modifiers', () => {
|
test('cache handler w/ modifiers', () => {
|
||||||
const {
|
const {
|
||||||
root,
|
root,
|
||||||
props: [prop]
|
props: [prop],
|
||||||
} = parseWithVOn(`<div @keyup.enter.capture="foo" />`, {
|
} = parseWithVOn(`<div @keyup.enter.capture="foo" />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
cacheHandlers: true
|
cacheHandlers: true,
|
||||||
})
|
})
|
||||||
expect(root.cached).toBe(1)
|
expect(root.cached).toBe(1)
|
||||||
// should not treat cached handler as dynamicProp, so it should have no
|
// should not treat cached handler as dynamicProp, so it should have no
|
||||||
// dynamicProps flags and only the hydration flag
|
// dynamicProps flags and only the hydration flag
|
||||||
expect((root as any).children[0].codegenNode.patchFlag).toBe(
|
expect((root as any).children[0].codegenNode.patchFlag).toBe(
|
||||||
genFlagText(PatchFlags.NEED_HYDRATION)
|
genFlagText(PatchFlags.NEED_HYDRATION),
|
||||||
)
|
)
|
||||||
expect(prop).toMatchObject({
|
expect(prop).toMatchObject({
|
||||||
key: {
|
key: {
|
||||||
content: `onKeyupCapture`
|
content: `onKeyupCapture`,
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||||
index: 0,
|
index: 0,
|
||||||
value: {
|
value: {
|
||||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||||
callee: V_ON_WITH_KEYS
|
callee: V_ON_WITH_KEYS,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -293,11 +293,11 @@ describe('compiler-dom: transform v-on', () => {
|
||||||
const { node } = parseWithVOn(`<div @keydown.up="foo" />`, {
|
const { node } = parseWithVOn(`<div @keydown.up="foo" />`, {
|
||||||
prefixIdentifiers: true,
|
prefixIdentifiers: true,
|
||||||
bindingMetadata: {
|
bindingMetadata: {
|
||||||
foo: BindingTypes.SETUP_CONST
|
foo: BindingTypes.SETUP_CONST,
|
||||||
},
|
},
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
on: transformOn
|
on: transformOn,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
// should only have hydration flag
|
// should only have hydration flag
|
||||||
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION))
|
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION))
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {
|
import {
|
||||||
|
type CompilerOptions,
|
||||||
|
generate,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
generate,
|
|
||||||
CompilerOptions
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||||
import { transformShow } from '../../src/transforms/vShow'
|
import { transformShow } from '../../src/transforms/vShow'
|
||||||
|
@ -13,9 +13,9 @@ function transformWithShow(template: string, options: CompilerOptions = {}) {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformElement],
|
nodeTransforms: [transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
show: transformShow
|
show: transformShow,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,8 @@ describe('compiler: v-show transform', () => {
|
||||||
expect(onError).toHaveBeenCalledTimes(1)
|
expect(onError).toHaveBeenCalledTimes(1)
|
||||||
expect(onError).toHaveBeenCalledWith(
|
expect(onError).toHaveBeenCalledWith(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: DOMErrorCodes.X_V_SHOW_NO_EXPRESSION
|
code: DOMErrorCodes.X_V_SHOW_NO_EXPRESSION,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
|
type CompilerOptions,
|
||||||
|
type PlainElementNode,
|
||||||
baseParse as parse,
|
baseParse as parse,
|
||||||
transform,
|
transform,
|
||||||
PlainElementNode,
|
|
||||||
CompilerOptions
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { transformVText } from '../../src/transforms/vText'
|
import { transformVText } from '../../src/transforms/vText'
|
||||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||||
import {
|
import {
|
||||||
createObjectMatcher,
|
createObjectMatcher,
|
||||||
genFlagText
|
genFlagText,
|
||||||
} from '../../../compiler-core/__tests__/testUtils'
|
} from '../../../compiler-core/__tests__/testUtils'
|
||||||
import { PatchFlags } from '@vue/shared'
|
import { PatchFlags } from '@vue/shared'
|
||||||
import { DOMErrorCodes } from '../../src/errors'
|
import { DOMErrorCodes } from '../../src/errors'
|
||||||
|
@ -18,9 +18,9 @@ function transformWithVText(template: string, options: CompilerOptions = {}) {
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [transformElement],
|
nodeTransforms: [transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
text: transformVText
|
text: transformVText,
|
||||||
},
|
},
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
return ast
|
return ast
|
||||||
}
|
}
|
||||||
|
@ -32,43 +32,43 @@ describe('compiler: v-text transform', () => {
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
textContent: {
|
textContent: {
|
||||||
arguments: [{ content: 'test' }]
|
arguments: [{ content: 'test' }],
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
children: undefined,
|
children: undefined,
|
||||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||||
dynamicProps: `["textContent"]`
|
dynamicProps: `["textContent"]`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should raise error and ignore children when v-text is present', () => {
|
it('should raise error and ignore children when v-text is present', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
const ast = transformWithVText(`<div v-text="test">hello</div>`, {
|
const ast = transformWithVText(`<div v-text="test">hello</div>`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError.mock.calls).toMatchObject([
|
expect(onError.mock.calls).toMatchObject([
|
||||||
[{ code: DOMErrorCodes.X_V_TEXT_WITH_CHILDREN }]
|
[{ code: DOMErrorCodes.X_V_TEXT_WITH_CHILDREN }],
|
||||||
])
|
])
|
||||||
expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({
|
expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({
|
||||||
tag: `"div"`,
|
tag: `"div"`,
|
||||||
props: createObjectMatcher({
|
props: createObjectMatcher({
|
||||||
textContent: {
|
textContent: {
|
||||||
arguments: [{ content: 'test' }]
|
arguments: [{ content: 'test' }],
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
children: undefined, // <-- children should have been removed
|
children: undefined, // <-- children should have been removed
|
||||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||||
dynamicProps: `["textContent"]`
|
dynamicProps: `["textContent"]`,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
it('should raise error if has no expression', () => {
|
it('should raise error if has no expression', () => {
|
||||||
const onError = vi.fn()
|
const onError = vi.fn()
|
||||||
transformWithVText(`<div v-text></div>`, {
|
transformWithVText(`<div v-text></div>`, {
|
||||||
onError
|
onError,
|
||||||
})
|
})
|
||||||
expect(onError.mock.calls).toMatchObject([
|
expect(onError.mock.calls).toMatchObject([
|
||||||
[{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }]
|
[{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }],
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {
|
import {
|
||||||
SourceLocation,
|
type CompilerError,
|
||||||
CompilerError,
|
ErrorCodes,
|
||||||
|
type SourceLocation,
|
||||||
createCompilerError,
|
createCompilerError,
|
||||||
ErrorCodes
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
|
|
||||||
export interface DOMCompilerError extends CompilerError {
|
export interface DOMCompilerError extends CompilerError {
|
||||||
|
@ -11,12 +11,12 @@ export interface DOMCompilerError extends CompilerError {
|
||||||
|
|
||||||
export function createDOMCompilerError(
|
export function createDOMCompilerError(
|
||||||
code: DOMErrorCodes,
|
code: DOMErrorCodes,
|
||||||
loc?: SourceLocation
|
loc?: SourceLocation,
|
||||||
) {
|
) {
|
||||||
return createCompilerError(
|
return createCompilerError(
|
||||||
code,
|
code,
|
||||||
loc,
|
loc,
|
||||||
__DEV__ || !__BROWSER__ ? DOMErrorMessages : undefined
|
__DEV__ || !__BROWSER__ ? DOMErrorMessages : undefined,
|
||||||
) as DOMCompilerError
|
) as DOMCompilerError
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ export enum DOMErrorCodes {
|
||||||
X_V_SHOW_NO_EXPRESSION,
|
X_V_SHOW_NO_EXPRESSION,
|
||||||
X_TRANSITION_INVALID_CHILDREN,
|
X_TRANSITION_INVALID_CHILDREN,
|
||||||
X_IGNORED_SIDE_EFFECT_TAG,
|
X_IGNORED_SIDE_EFFECT_TAG,
|
||||||
__EXTEND_POINT__
|
__EXTEND_POINT__,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (__TEST__) {
|
if (__TEST__) {
|
||||||
|
@ -43,7 +43,7 @@ if (__TEST__) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`DOMErrorCodes need to be updated to ${
|
`DOMErrorCodes need to be updated to ${
|
||||||
ErrorCodes.__EXTEND_POINT__ + 1
|
ErrorCodes.__EXTEND_POINT__ + 1
|
||||||
} to match extension point from core ErrorCodes.`
|
} to match extension point from core ErrorCodes.`,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -59,5 +59,5 @@ export const DOMErrorMessages: { [code: number]: string } = {
|
||||||
[DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,
|
[DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE]: `Unnecessary value binding used alongside v-model. It will interfere with v-model's behavior.`,
|
||||||
[DOMErrorCodes.X_V_SHOW_NO_EXPRESSION]: `v-show is missing expression.`,
|
[DOMErrorCodes.X_V_SHOW_NO_EXPRESSION]: `v-show is missing expression.`,
|
||||||
[DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN]: `<Transition> expects exactly one child element or component.`,
|
[DOMErrorCodes.X_TRANSITION_INVALID_CHILDREN]: `<Transition> expects exactly one child element or component.`,
|
||||||
[DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`
|
[DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG]: `Tags with side effect (<script> and <style>) are ignored in client component templates.`,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import {
|
import {
|
||||||
|
type CodegenResult,
|
||||||
|
type CompilerOptions,
|
||||||
|
type DirectiveTransform,
|
||||||
|
type NodeTransform,
|
||||||
|
type ParserOptions,
|
||||||
|
type RootNode,
|
||||||
baseCompile,
|
baseCompile,
|
||||||
baseParse,
|
baseParse,
|
||||||
CompilerOptions,
|
|
||||||
CodegenResult,
|
|
||||||
ParserOptions,
|
|
||||||
RootNode,
|
|
||||||
noopDirectiveTransform,
|
noopDirectiveTransform,
|
||||||
NodeTransform,
|
|
||||||
DirectiveTransform
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { parserOptions } from './parserOptions'
|
import { parserOptions } from './parserOptions'
|
||||||
import { transformStyle } from './transforms/transformStyle'
|
import { transformStyle } from './transforms/transformStyle'
|
||||||
|
@ -25,7 +25,7 @@ export { parserOptions }
|
||||||
|
|
||||||
export const DOMNodeTransforms: NodeTransform[] = [
|
export const DOMNodeTransforms: NodeTransform[] = [
|
||||||
transformStyle,
|
transformStyle,
|
||||||
...(__DEV__ ? [transformTransition] : [])
|
...(__DEV__ ? [transformTransition] : []),
|
||||||
]
|
]
|
||||||
|
|
||||||
export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
|
export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
|
||||||
|
@ -34,12 +34,12 @@ export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
|
||||||
text: transformVText,
|
text: transformVText,
|
||||||
model: transformModel, // override compiler-core
|
model: transformModel, // override compiler-core
|
||||||
on: transformOn, // override compiler-core
|
on: transformOn, // override compiler-core
|
||||||
show: transformShow
|
show: transformShow,
|
||||||
}
|
}
|
||||||
|
|
||||||
export function compile(
|
export function compile(
|
||||||
src: string | RootNode,
|
src: string | RootNode,
|
||||||
options: CompilerOptions = {}
|
options: CompilerOptions = {},
|
||||||
): CodegenResult {
|
): CodegenResult {
|
||||||
return baseCompile(
|
return baseCompile(
|
||||||
src,
|
src,
|
||||||
|
@ -50,15 +50,15 @@ export function compile(
|
||||||
// by compiler-ssr to generate vnode fallback branches
|
// by compiler-ssr to generate vnode fallback branches
|
||||||
ignoreSideEffectTags,
|
ignoreSideEffectTags,
|
||||||
...DOMNodeTransforms,
|
...DOMNodeTransforms,
|
||||||
...(options.nodeTransforms || [])
|
...(options.nodeTransforms || []),
|
||||||
],
|
],
|
||||||
directiveTransforms: extend(
|
directiveTransforms: extend(
|
||||||
{},
|
{},
|
||||||
DOMDirectiveTransforms,
|
DOMDirectiveTransforms,
|
||||||
options.directiveTransforms || {}
|
options.directiveTransforms || {},
|
||||||
),
|
),
|
||||||
transformHoist: __BROWSER__ ? null : stringifyStatic
|
transformHoist: __BROWSER__ ? null : stringifyStatic,
|
||||||
})
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,6 @@ export { transformStyle } from './transforms/transformStyle'
|
||||||
export {
|
export {
|
||||||
createDOMCompilerError,
|
createDOMCompilerError,
|
||||||
DOMErrorCodes,
|
DOMErrorCodes,
|
||||||
DOMErrorMessages
|
DOMErrorMessages,
|
||||||
} from './errors'
|
} from './errors'
|
||||||
export * from '@vue/compiler-core'
|
export * from '@vue/compiler-core'
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { ParserOptions, NodeTypes, Namespaces } from '@vue/compiler-core'
|
import { Namespaces, NodeTypes, type ParserOptions } from '@vue/compiler-core'
|
||||||
import { isVoidTag, isHTMLTag, isSVGTag, isMathMLTag } from '@vue/shared'
|
import { isHTMLTag, isMathMLTag, isSVGTag, isVoidTag } from '@vue/shared'
|
||||||
import { TRANSITION, TRANSITION_GROUP } from './runtimeHelpers'
|
import { TRANSITION, TRANSITION_GROUP } from './runtimeHelpers'
|
||||||
import { decodeHtmlBrowser } from './decodeHtmlBrowser'
|
import { decodeHtmlBrowser } from './decodeHtmlBrowser'
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ export const parserOptions: ParserOptions = {
|
||||||
a.name === 'encoding' &&
|
a.name === 'encoding' &&
|
||||||
a.value != null &&
|
a.value != null &&
|
||||||
(a.value.content === 'text/html' ||
|
(a.value.content === 'text/html' ||
|
||||||
a.value.content === 'application/xhtml+xml')
|
a.value.content === 'application/xhtml+xml'),
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
ns = Namespaces.HTML
|
ns = Namespaces.HTML
|
||||||
|
@ -64,5 +64,5 @@ export const parserOptions: ParserOptions = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ns
|
return ns
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,5 +24,5 @@ registerRuntimeHelpers({
|
||||||
[V_ON_WITH_KEYS]: `withKeys`,
|
[V_ON_WITH_KEYS]: `withKeys`,
|
||||||
[V_SHOW]: `vShow`,
|
[V_SHOW]: `vShow`,
|
||||||
[TRANSITION]: `Transition`,
|
[TRANSITION]: `Transition`,
|
||||||
[TRANSITION_GROUP]: `TransitionGroup`
|
[TRANSITION_GROUP]: `TransitionGroup`,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import {
|
import {
|
||||||
NodeTransform,
|
type ComponentNode,
|
||||||
NodeTypes,
|
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
ComponentNode,
|
type IfBranchNode,
|
||||||
IfBranchNode
|
type NodeTransform,
|
||||||
|
NodeTypes,
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { TRANSITION } from '../runtimeHelpers'
|
import { TRANSITION } from '../runtimeHelpers'
|
||||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||||
|
|
||||||
export const transformTransition: NodeTransform = (node, context) => {
|
export const transformTransition: NodeTransform = (node, context) => {
|
||||||
if (
|
if (
|
||||||
|
@ -28,9 +28,9 @@ export const transformTransition: NodeTransform = (node, context) => {
|
||||||
{
|
{
|
||||||
start: node.children[0].loc.start,
|
start: node.children[0].loc.start,
|
||||||
end: node.children[node.children.length - 1].loc.end,
|
end: node.children[node.children.length - 1].loc.end,
|
||||||
source: ''
|
source: '',
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ export const transformTransition: NodeTransform = (node, context) => {
|
||||||
name: 'persisted',
|
name: 'persisted',
|
||||||
nameLoc: node.loc,
|
nameLoc: node.loc,
|
||||||
value: undefined,
|
value: undefined,
|
||||||
loc: node.loc
|
loc: node.loc,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,7 @@ function hasMultipleChildren(node: ComponentNode | IfBranchNode): boolean {
|
||||||
const children = (node.children = node.children.filter(
|
const children = (node.children = node.children.filter(
|
||||||
c =>
|
c =>
|
||||||
c.type !== NodeTypes.COMMENT &&
|
c.type !== NodeTypes.COMMENT &&
|
||||||
!(c.type === NodeTypes.TEXT && !c.content.trim())
|
!(c.type === NodeTypes.TEXT && !c.content.trim()),
|
||||||
))
|
))
|
||||||
const child = children[0]
|
const child = children[0]
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { NodeTransform, NodeTypes, ElementTypes } from '@vue/compiler-core'
|
import { ElementTypes, type NodeTransform, NodeTypes } from '@vue/compiler-core'
|
||||||
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||||
|
|
||||||
export const ignoreSideEffectTags: NodeTransform = (node, context) => {
|
export const ignoreSideEffectTags: NodeTransform = (node, context) => {
|
||||||
|
@ -11,8 +11,8 @@ export const ignoreSideEffectTags: NodeTransform = (node, context) => {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG,
|
DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG,
|
||||||
node.loc
|
node.loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
context.removeNode()
|
context.removeNode()
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,40 +2,40 @@
|
||||||
* This module is Node-only.
|
* This module is Node-only.
|
||||||
*/
|
*/
|
||||||
import {
|
import {
|
||||||
NodeTypes,
|
|
||||||
ElementNode,
|
|
||||||
TransformContext,
|
|
||||||
TemplateChildNode,
|
|
||||||
SimpleExpressionNode,
|
|
||||||
createCallExpression,
|
|
||||||
HoistTransform,
|
|
||||||
CREATE_STATIC,
|
CREATE_STATIC,
|
||||||
ExpressionNode,
|
|
||||||
ElementTypes,
|
|
||||||
PlainElementNode,
|
|
||||||
JSChildNode,
|
|
||||||
TextCallNode,
|
|
||||||
ConstantTypes,
|
ConstantTypes,
|
||||||
Namespaces
|
type ElementNode,
|
||||||
|
ElementTypes,
|
||||||
|
type ExpressionNode,
|
||||||
|
type HoistTransform,
|
||||||
|
type JSChildNode,
|
||||||
|
Namespaces,
|
||||||
|
NodeTypes,
|
||||||
|
type PlainElementNode,
|
||||||
|
type SimpleExpressionNode,
|
||||||
|
type TemplateChildNode,
|
||||||
|
type TextCallNode,
|
||||||
|
type TransformContext,
|
||||||
|
createCallExpression,
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import {
|
import {
|
||||||
isVoidTag,
|
escapeHtml,
|
||||||
|
isBooleanAttr,
|
||||||
|
isKnownHtmlAttr,
|
||||||
|
isKnownSvgAttr,
|
||||||
isString,
|
isString,
|
||||||
isSymbol,
|
isSymbol,
|
||||||
isKnownHtmlAttr,
|
isVoidTag,
|
||||||
escapeHtml,
|
makeMap,
|
||||||
toDisplayString,
|
|
||||||
normalizeClass,
|
normalizeClass,
|
||||||
normalizeStyle,
|
normalizeStyle,
|
||||||
stringifyStyle,
|
stringifyStyle,
|
||||||
makeMap,
|
toDisplayString,
|
||||||
isKnownSvgAttr,
|
|
||||||
isBooleanAttr
|
|
||||||
} from '@vue/shared'
|
} from '@vue/shared'
|
||||||
|
|
||||||
export enum StringifyThresholds {
|
export enum StringifyThresholds {
|
||||||
ELEMENT_WITH_BINDING_COUNT = 5,
|
ELEMENT_WITH_BINDING_COUNT = 5,
|
||||||
NODE_COUNT = 20
|
NODE_COUNT = 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
type StringifiableNode = PlainElementNode | TextCallNode
|
type StringifiableNode = PlainElementNode | TextCallNode
|
||||||
|
@ -87,11 +87,11 @@ export const stringifyStatic: HoistTransform = (children, context, parent) => {
|
||||||
// combine all currently eligible nodes into a single static vnode call
|
// combine all currently eligible nodes into a single static vnode call
|
||||||
const staticCall = createCallExpression(context.helper(CREATE_STATIC), [
|
const staticCall = createCallExpression(context.helper(CREATE_STATIC), [
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
currentChunk.map(node => stringifyNode(node, context)).join('')
|
currentChunk.map(node => stringifyNode(node, context)).join(''),
|
||||||
).replace(expReplaceRE, `" + $1 + "`),
|
).replace(expReplaceRE, `" + $1 + "`),
|
||||||
// the 2nd argument indicates the number of DOM nodes this static vnode
|
// the 2nd argument indicates the number of DOM nodes this static vnode
|
||||||
// will insert / hydrate
|
// will insert / hydrate
|
||||||
String(currentChunk.length)
|
String(currentChunk.length),
|
||||||
])
|
])
|
||||||
// replace the first node's hoisted expression with the static vnode call
|
// replace the first node's hoisted expression with the static vnode call
|
||||||
replaceHoist(currentChunk[0], staticCall, context)
|
replaceHoist(currentChunk[0], staticCall, context)
|
||||||
|
@ -161,14 +161,14 @@ const isStringifiableAttr = (name: string, ns: Namespaces) => {
|
||||||
const replaceHoist = (
|
const replaceHoist = (
|
||||||
node: StringifiableNode,
|
node: StringifiableNode,
|
||||||
replacement: JSChildNode | null,
|
replacement: JSChildNode | null,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
) => {
|
) => {
|
||||||
const hoistToReplace = (node.codegenNode as SimpleExpressionNode).hoisted!
|
const hoistToReplace = (node.codegenNode as SimpleExpressionNode).hoisted!
|
||||||
context.hoists[context.hoists.indexOf(hoistToReplace)] = replacement
|
context.hoists[context.hoists.indexOf(hoistToReplace)] = replacement
|
||||||
}
|
}
|
||||||
|
|
||||||
const isNonStringifiable = /*#__PURE__*/ makeMap(
|
const isNonStringifiable = /*#__PURE__*/ makeMap(
|
||||||
`caption,thead,tr,th,tbody,td,tfoot,colgroup,col`
|
`caption,thead,tr,th,tbody,td,tfoot,colgroup,col`,
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -248,7 +248,7 @@ function analyzeNode(node: StringifiableNode): [number, number] | false {
|
||||||
|
|
||||||
function stringifyNode(
|
function stringifyNode(
|
||||||
node: string | TemplateChildNode,
|
node: string | TemplateChildNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): string {
|
): string {
|
||||||
if (isString(node)) {
|
if (isString(node)) {
|
||||||
return node
|
return node
|
||||||
|
@ -277,7 +277,7 @@ function stringifyNode(
|
||||||
|
|
||||||
function stringifyElement(
|
function stringifyElement(
|
||||||
node: ElementNode,
|
node: ElementNode,
|
||||||
context: TransformContext
|
context: TransformContext,
|
||||||
): string {
|
): string {
|
||||||
let res = `<${node.tag}`
|
let res = `<${node.tag}`
|
||||||
let innerHTML = ''
|
let innerHTML = ''
|
||||||
|
@ -316,7 +316,7 @@ function stringifyElement(
|
||||||
evaluated = stringifyStyle(normalizeStyle(evaluated))
|
evaluated = stringifyStyle(normalizeStyle(evaluated))
|
||||||
}
|
}
|
||||||
res += ` ${(p.arg as SimpleExpressionNode).content}="${escapeHtml(
|
res += ` ${(p.arg as SimpleExpressionNode).content}="${escapeHtml(
|
||||||
evaluated
|
evaluated,
|
||||||
)}"`
|
)}"`
|
||||||
}
|
}
|
||||||
} else if (p.name === 'html') {
|
} else if (p.name === 'html') {
|
||||||
|
@ -325,7 +325,7 @@ function stringifyElement(
|
||||||
innerHTML = evaluateConstant(p.exp as SimpleExpressionNode)
|
innerHTML = evaluateConstant(p.exp as SimpleExpressionNode)
|
||||||
} else if (p.name === 'text') {
|
} else if (p.name === 'text') {
|
||||||
innerHTML = escapeHtml(
|
innerHTML = escapeHtml(
|
||||||
toDisplayString(evaluateConstant(p.exp as SimpleExpressionNode))
|
toDisplayString(evaluateConstant(p.exp as SimpleExpressionNode)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import {
|
import {
|
||||||
NodeTransform,
|
ConstantTypes,
|
||||||
|
type NodeTransform,
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
|
type SimpleExpressionNode,
|
||||||
|
type SourceLocation,
|
||||||
createSimpleExpression,
|
createSimpleExpression,
|
||||||
SimpleExpressionNode,
|
|
||||||
SourceLocation,
|
|
||||||
ConstantTypes
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { parseStringStyle } from '@vue/shared'
|
import { parseStringStyle } from '@vue/shared'
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ export const transformStyle: NodeTransform = node => {
|
||||||
arg: createSimpleExpression(`style`, true, p.loc),
|
arg: createSimpleExpression(`style`, true, p.loc),
|
||||||
exp: parseInlineCSS(p.value.content, p.loc),
|
exp: parseInlineCSS(p.value.content, p.loc),
|
||||||
modifiers: [],
|
modifiers: [],
|
||||||
loc: p.loc
|
loc: p.loc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -34,13 +34,13 @@ export const transformStyle: NodeTransform = node => {
|
||||||
|
|
||||||
const parseInlineCSS = (
|
const parseInlineCSS = (
|
||||||
cssText: string,
|
cssText: string,
|
||||||
loc: SourceLocation
|
loc: SourceLocation,
|
||||||
): SimpleExpressionNode => {
|
): SimpleExpressionNode => {
|
||||||
const normalized = parseStringStyle(cssText)
|
const normalized = parseStringStyle(cssText)
|
||||||
return createSimpleExpression(
|
return createSimpleExpression(
|
||||||
JSON.stringify(normalized),
|
JSON.stringify(normalized),
|
||||||
false,
|
false,
|
||||||
loc,
|
loc,
|
||||||
ConstantTypes.CAN_STRINGIFY
|
ConstantTypes.CAN_STRINGIFY,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import {
|
import {
|
||||||
DirectiveTransform,
|
type DirectiveTransform,
|
||||||
createObjectProperty,
|
createObjectProperty,
|
||||||
createSimpleExpression
|
createSimpleExpression,
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||||
|
|
||||||
export const transformVHtml: DirectiveTransform = (dir, node, context) => {
|
export const transformVHtml: DirectiveTransform = (dir, node, context) => {
|
||||||
const { exp, loc } = dir
|
const { exp, loc } = dir
|
||||||
if (!exp) {
|
if (!exp) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc)
|
createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (node.children.length) {
|
if (node.children.length) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc)
|
createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc),
|
||||||
)
|
)
|
||||||
node.children.length = 0
|
node.children.length = 0
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,8 @@ export const transformVHtml: DirectiveTransform = (dir, node, context) => {
|
||||||
props: [
|
props: [
|
||||||
createObjectProperty(
|
createObjectProperty(
|
||||||
createSimpleExpression(`innerHTML`, true, loc),
|
createSimpleExpression(`innerHTML`, true, loc),
|
||||||
exp || createSimpleExpression('', true)
|
exp || createSimpleExpression('', true),
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import {
|
import {
|
||||||
transformModel as baseTransform,
|
type DirectiveTransform,
|
||||||
DirectiveTransform,
|
|
||||||
ElementTypes,
|
ElementTypes,
|
||||||
findProp,
|
|
||||||
NodeTypes,
|
NodeTypes,
|
||||||
hasDynamicKeyVBind,
|
transformModel as baseTransform,
|
||||||
findDir,
|
findDir,
|
||||||
isStaticArgOf
|
findProp,
|
||||||
|
hasDynamicKeyVBind,
|
||||||
|
isStaticArgOf,
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||||
import {
|
import {
|
||||||
V_MODEL_CHECKBOX,
|
V_MODEL_CHECKBOX,
|
||||||
|
V_MODEL_DYNAMIC,
|
||||||
V_MODEL_RADIO,
|
V_MODEL_RADIO,
|
||||||
V_MODEL_SELECT,
|
V_MODEL_SELECT,
|
||||||
V_MODEL_TEXT,
|
V_MODEL_TEXT,
|
||||||
V_MODEL_DYNAMIC
|
|
||||||
} from '../runtimeHelpers'
|
} from '../runtimeHelpers'
|
||||||
|
|
||||||
export const transformModel: DirectiveTransform = (dir, node, context) => {
|
export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
|
@ -28,8 +28,8 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
|
DOMErrorCodes.X_V_MODEL_ARG_ON_ELEMENT,
|
||||||
dir.arg.loc
|
dir.arg.loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,
|
DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,
|
||||||
value.loc
|
value.loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,8 +74,8 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
||||||
dir.loc
|
dir.loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
@ -108,8 +108,8 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(
|
createDOMCompilerError(
|
||||||
DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
|
DOMErrorCodes.X_V_MODEL_ON_INVALID_ELEMENT,
|
||||||
dir.loc
|
dir.loc,
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||||
!(
|
!(
|
||||||
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
|
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
|
||||||
p.key.content === 'modelValue'
|
p.key.content === 'modelValue'
|
||||||
)
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
return baseResult
|
return baseResult
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
import {
|
import {
|
||||||
transformOn as baseTransform,
|
|
||||||
DirectiveTransform,
|
|
||||||
createObjectProperty,
|
|
||||||
createCallExpression,
|
|
||||||
createSimpleExpression,
|
|
||||||
NodeTypes,
|
|
||||||
createCompoundExpression,
|
|
||||||
ExpressionNode,
|
|
||||||
SimpleExpressionNode,
|
|
||||||
isStaticExp,
|
|
||||||
CompilerDeprecationTypes,
|
CompilerDeprecationTypes,
|
||||||
TransformContext,
|
type DirectiveTransform,
|
||||||
SourceLocation,
|
type ExpressionNode,
|
||||||
checkCompatEnabled
|
NodeTypes,
|
||||||
|
type SimpleExpressionNode,
|
||||||
|
type SourceLocation,
|
||||||
|
type TransformContext,
|
||||||
|
transformOn as baseTransform,
|
||||||
|
checkCompatEnabled,
|
||||||
|
createCallExpression,
|
||||||
|
createCompoundExpression,
|
||||||
|
createObjectProperty,
|
||||||
|
createSimpleExpression,
|
||||||
|
isStaticExp,
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers'
|
import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../runtimeHelpers'
|
||||||
import { makeMap, capitalize } from '@vue/shared'
|
import { capitalize, makeMap } from '@vue/shared'
|
||||||
|
|
||||||
const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
|
const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
|
||||||
const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
||||||
|
@ -24,20 +24,20 @@ const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
||||||
// system modifiers + exact
|
// system modifiers + exact
|
||||||
`ctrl,shift,alt,meta,exact,` +
|
`ctrl,shift,alt,meta,exact,` +
|
||||||
// mouse
|
// mouse
|
||||||
`middle`
|
`middle`,
|
||||||
)
|
)
|
||||||
// left & right could be mouse or key modifiers based on event type
|
// left & right could be mouse or key modifiers based on event type
|
||||||
const maybeKeyModifier = /*#__PURE__*/ makeMap('left,right')
|
const maybeKeyModifier = /*#__PURE__*/ makeMap('left,right')
|
||||||
const isKeyboardEvent = /*#__PURE__*/ makeMap(
|
const isKeyboardEvent = /*#__PURE__*/ makeMap(
|
||||||
`onkeyup,onkeydown,onkeypress`,
|
`onkeyup,onkeydown,onkeypress`,
|
||||||
true
|
true,
|
||||||
)
|
)
|
||||||
|
|
||||||
const resolveModifiers = (
|
const resolveModifiers = (
|
||||||
key: ExpressionNode,
|
key: ExpressionNode,
|
||||||
modifiers: string[],
|
modifiers: string[],
|
||||||
context: TransformContext,
|
context: TransformContext,
|
||||||
loc: SourceLocation
|
loc: SourceLocation,
|
||||||
) => {
|
) => {
|
||||||
const keyModifiers = []
|
const keyModifiers = []
|
||||||
const nonKeyModifiers = []
|
const nonKeyModifiers = []
|
||||||
|
@ -52,7 +52,7 @@ const resolveModifiers = (
|
||||||
checkCompatEnabled(
|
checkCompatEnabled(
|
||||||
CompilerDeprecationTypes.COMPILER_V_ON_NATIVE,
|
CompilerDeprecationTypes.COMPILER_V_ON_NATIVE,
|
||||||
context,
|
context,
|
||||||
loc
|
loc,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
eventOptionModifiers.push(modifier)
|
eventOptionModifiers.push(modifier)
|
||||||
|
@ -86,7 +86,7 @@ const resolveModifiers = (
|
||||||
return {
|
return {
|
||||||
keyModifiers,
|
keyModifiers,
|
||||||
nonKeyModifiers,
|
nonKeyModifiers,
|
||||||
eventOptionModifiers
|
eventOptionModifiers,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ const transformClick = (key: ExpressionNode, event: string) => {
|
||||||
key,
|
key,
|
||||||
`) === "onClick" ? "${event}" : (`,
|
`) === "onClick" ? "${event}" : (`,
|
||||||
key,
|
key,
|
||||||
`)`
|
`)`,
|
||||||
])
|
])
|
||||||
: key
|
: key
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
|
||||||
if (nonKeyModifiers.length) {
|
if (nonKeyModifiers.length) {
|
||||||
handlerExp = createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [
|
handlerExp = createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [
|
||||||
handlerExp,
|
handlerExp,
|
||||||
JSON.stringify(nonKeyModifiers)
|
JSON.stringify(nonKeyModifiers),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,7 +137,7 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
|
||||||
) {
|
) {
|
||||||
handlerExp = createCallExpression(context.helper(V_ON_WITH_KEYS), [
|
handlerExp = createCallExpression(context.helper(V_ON_WITH_KEYS), [
|
||||||
handlerExp,
|
handlerExp,
|
||||||
JSON.stringify(keyModifiers)
|
JSON.stringify(keyModifiers),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +149,7 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: [createObjectProperty(key, handlerExp)]
|
props: [createObjectProperty(key, handlerExp)],
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import { DirectiveTransform } from '@vue/compiler-core'
|
import type { DirectiveTransform } from '@vue/compiler-core'
|
||||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||||
import { V_SHOW } from '../runtimeHelpers'
|
import { V_SHOW } from '../runtimeHelpers'
|
||||||
|
|
||||||
export const transformShow: DirectiveTransform = (dir, node, context) => {
|
export const transformShow: DirectiveTransform = (dir, node, context) => {
|
||||||
const { exp, loc } = dir
|
const { exp, loc } = dir
|
||||||
if (!exp) {
|
if (!exp) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc)
|
createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
props: [],
|
props: [],
|
||||||
needRuntime: context.helper(V_SHOW)
|
needRuntime: context.helper(V_SHOW),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
import {
|
import {
|
||||||
DirectiveTransform,
|
type DirectiveTransform,
|
||||||
createObjectProperty,
|
|
||||||
createSimpleExpression,
|
|
||||||
TO_DISPLAY_STRING,
|
TO_DISPLAY_STRING,
|
||||||
createCallExpression,
|
createCallExpression,
|
||||||
getConstantType
|
createObjectProperty,
|
||||||
|
createSimpleExpression,
|
||||||
|
getConstantType,
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||||
|
|
||||||
export const transformVText: DirectiveTransform = (dir, node, context) => {
|
export const transformVText: DirectiveTransform = (dir, node, context) => {
|
||||||
const { exp, loc } = dir
|
const { exp, loc } = dir
|
||||||
if (!exp) {
|
if (!exp) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc)
|
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (node.children.length) {
|
if (node.children.length) {
|
||||||
context.onError(
|
context.onError(
|
||||||
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc)
|
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc),
|
||||||
)
|
)
|
||||||
node.children.length = 0
|
node.children.length = 0
|
||||||
}
|
}
|
||||||
|
@ -31,10 +31,10 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
|
||||||
: createCallExpression(
|
: createCallExpression(
|
||||||
context.helperString(TO_DISPLAY_STRING),
|
context.helperString(TO_DISPLAY_STRING),
|
||||||
[exp],
|
[exp],
|
||||||
loc
|
loc,
|
||||||
)
|
)
|
||||||
: createSimpleExpression('', true)
|
: createSimpleExpression('', true),
|
||||||
)
|
),
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BindingTypes } from '@vue/compiler-core'
|
import { BindingTypes } from '@vue/compiler-core'
|
||||||
import { compileSFCScript as compile, assertCode, mockId } from './utils'
|
import { assertCode, compileSFCScript as compile, mockId } from './utils'
|
||||||
|
|
||||||
describe('SFC compile <script setup>', () => {
|
describe('SFC compile <script setup>', () => {
|
||||||
test('should compile JS syntax', () => {
|
test('should compile JS syntax', () => {
|
||||||
|
@ -34,7 +34,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`return { get aa() { return aa }, set aa(v) { aa = v }, ` +
|
`return { get aa() { return aa }, set aa(v) { aa = v }, ` +
|
||||||
`bb, cc, dd, get a() { return a }, set a(v) { a = v }, b, c, d, ` +
|
`bb, cc, dd, get a() { return a }, set a(v) { a = v }, b, c, d, ` +
|
||||||
`get xx() { return xx }, get x() { return x } }`
|
`get xx() { return xx }, get x() { return x } }`,
|
||||||
)
|
)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
x: BindingTypes.SETUP_MAYBE_REF,
|
x: BindingTypes.SETUP_MAYBE_REF,
|
||||||
|
@ -46,7 +46,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
aa: BindingTypes.SETUP_LET,
|
aa: BindingTypes.SETUP_LET,
|
||||||
bb: BindingTypes.LITERAL_CONST,
|
bb: BindingTypes.LITERAL_CONST,
|
||||||
cc: BindingTypes.SETUP_CONST,
|
cc: BindingTypes.SETUP_CONST,
|
||||||
dd: BindingTypes.SETUP_CONST
|
dd: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -63,7 +63,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
bar: BindingTypes.SETUP_MAYBE_REF,
|
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||||
baz: BindingTypes.SETUP_MAYBE_REF,
|
baz: BindingTypes.SETUP_MAYBE_REF,
|
||||||
y: BindingTypes.SETUP_MAYBE_REF,
|
y: BindingTypes.SETUP_MAYBE_REF,
|
||||||
z: BindingTypes.SETUP_MAYBE_REF
|
z: BindingTypes.SETUP_MAYBE_REF,
|
||||||
})
|
})
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -209,7 +209,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
compile(`<script setup>
|
compile(`<script setup>
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import 'foo/css'
|
import 'foo/css'
|
||||||
</script>`).content
|
</script>`).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
import a from 'a' // comment
|
import a from 'a' // comment
|
||||||
import b from 'b'
|
import b from 'b'
|
||||||
</script>
|
</script>
|
||||||
`).content
|
`).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
defineProps(['foo'])
|
defineProps(['foo'])
|
||||||
defineEmits(['bar'])
|
defineEmits(['bar'])
|
||||||
const r = ref(0)
|
const r = ref(0)
|
||||||
</script>`).content
|
</script>`).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -249,11 +249,11 @@ describe('SFC compile <script setup>', () => {
|
||||||
color: v-bind(msg)
|
color: v-bind(msg)
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`
|
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`import { useCssVars, ref } from 'vue'`)
|
expect(content).toMatch(`import { useCssVars, ref } from 'vue'`)
|
||||||
})
|
})
|
||||||
|
@ -270,7 +270,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
`)
|
`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content.indexOf(`import { x }`)).toEqual(
|
expect(content.indexOf(`import { x }`)).toEqual(
|
||||||
content.lastIndexOf(`import { x }`)
|
content.lastIndexOf(`import { x }`),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
ref: BindingTypes.SETUP_MAYBE_REF,
|
ref: BindingTypes.SETUP_MAYBE_REF,
|
||||||
reactive: BindingTypes.SETUP_MAYBE_REF,
|
reactive: BindingTypes.SETUP_MAYBE_REF,
|
||||||
foo: BindingTypes.SETUP_MAYBE_REF,
|
foo: BindingTypes.SETUP_MAYBE_REF,
|
||||||
bar: BindingTypes.SETUP_MAYBE_REF
|
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
_reactive: BindingTypes.SETUP_MAYBE_REF,
|
_reactive: BindingTypes.SETUP_MAYBE_REF,
|
||||||
_ref: BindingTypes.SETUP_MAYBE_REF,
|
_ref: BindingTypes.SETUP_MAYBE_REF,
|
||||||
foo: BindingTypes.SETUP_MAYBE_REF,
|
foo: BindingTypes.SETUP_MAYBE_REF,
|
||||||
bar: BindingTypes.SETUP_MAYBE_REF
|
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -318,7 +318,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
bar: BindingTypes.SETUP_REACTIVE_CONST,
|
bar: BindingTypes.SETUP_REACTIVE_CONST,
|
||||||
x: BindingTypes.SETUP_CONST
|
x: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -334,7 +334,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
`)
|
`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.SETUP_MAYBE_REF
|
foo: BindingTypes.SETUP_MAYBE_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -363,7 +363,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
// foo: lowercase component
|
// foo: lowercase component
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`return { fooBar, get FooBaz() { return FooBaz }, ` +
|
`return { fooBar, get FooBaz() { return FooBaz }, ` +
|
||||||
`get FooQux() { return FooQux }, get foo() { return foo } }`
|
`get FooQux() { return FooQux }, get foo() { return foo } }`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -396,7 +396,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
`)
|
`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`return { get FooBar() { return FooBar }, get foo() { return foo }, ` +
|
`return { get FooBar() { return FooBar }, get foo() { return foo }, ` +
|
||||||
`get bar() { return bar }, get baz() { return baz } }`
|
`get bar() { return bar }, get baz() { return baz } }`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -413,7 +413,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
</template>
|
</template>
|
||||||
`)
|
`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`return { cond, get bar() { return bar }, get baz() { return baz } }`
|
`return { cond, get bar() { return bar }, get baz() { return baz } }`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -431,7 +431,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
// y: should not be matched by {{ yy }} or 'y' in binding exps
|
// y: should not be matched by {{ yy }} or 'y' in binding exps
|
||||||
// x$y: #4274 should escape special chars when creating Regex
|
// x$y: #4274 should escape special chars when creating Regex
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`return { get x() { return x }, get z() { return z }, get x$y() { return x$y } }`
|
`return { get x() { return x }, get z() { return z }, get x$y() { return x$y } }`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -448,7 +448,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
`)
|
`)
|
||||||
// VAR2 should not be matched
|
// VAR2 should not be matched
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`return { get VAR() { return VAR }, get VAR3() { return VAR3 } }`
|
`return { get VAR() { return VAR }, get VAR3() { return VAR3 } }`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -465,7 +465,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
</template>
|
</template>
|
||||||
`)
|
`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`return { get FooBaz() { return FooBaz }, get Last() { return Last } }`
|
`return { get FooBaz() { return FooBaz }, get Last() { return Last } }`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -514,7 +514,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
</template>
|
</template>
|
||||||
`)
|
`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
'return { get foo() { return foo }, get bar() { return bar }, get Baz() { return Baz } }'
|
'return { get foo() { return foo }, get bar() { return bar }, get Baz() { return Baz } }',
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -573,7 +573,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
<div>static</div>
|
<div>static</div>
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
// check snapshot and make sure helper imports and
|
// check snapshot and make sure helper imports and
|
||||||
// hoists are placed correctly.
|
// hoists are placed correctly.
|
||||||
|
@ -591,7 +591,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
defineExpose({ count })
|
defineExpose({ count })
|
||||||
</script>
|
</script>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`setup(__props, { expose: __expose })`)
|
expect(content).toMatch(`setup(__props, { expose: __expose })`)
|
||||||
|
@ -612,7 +612,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
<some-other-comp/>
|
<some-other-comp/>
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
expect(content).toMatch('[_unref(vMyDir)]')
|
expect(content).toMatch('[_unref(vMyDir)]')
|
||||||
expect(content).toMatch('_createVNode(ChildComp)')
|
expect(content).toMatch('_createVNode(ChildComp)')
|
||||||
|
@ -641,7 +641,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
{{ tree.foo() }}
|
{{ tree.foo() }}
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
// no need to unref vue component import
|
// no need to unref vue component import
|
||||||
expect(content).toMatch(`createVNode(Foo,`)
|
expect(content).toMatch(`createVNode(Foo,`)
|
||||||
|
@ -680,7 +680,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
<input v-model="lett">
|
<input v-model="lett">
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
// known const ref: set value
|
// known const ref: set value
|
||||||
expect(content).toMatch(`(count).value = $event`)
|
expect(content).toMatch(`(count).value = $event`)
|
||||||
|
@ -688,7 +688,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
expect(content).toMatch(`_isRef(maybe) ? (maybe).value = $event : null`)
|
expect(content).toMatch(`_isRef(maybe) ? (maybe).value = $event : null`)
|
||||||
// let: handle both cases
|
// let: handle both cases
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`_isRef(lett) ? (lett).value = $event : lett = $event`
|
`_isRef(lett) ? (lett).value = $event : lett = $event`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -708,7 +708,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
<input v-model="foo">
|
<input v-model="foo">
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch(`_isRef(foo)`)
|
expect(content).not.toMatch(`_isRef(foo)`)
|
||||||
})
|
})
|
||||||
|
@ -746,7 +746,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
}"/>
|
}"/>
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
// known const ref: set value
|
// known const ref: set value
|
||||||
expect(content).toMatch(`count.value = 1`)
|
expect(content).toMatch(`count.value = 1`)
|
||||||
|
@ -754,7 +754,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
expect(content).toMatch(`maybe.value = count.value`)
|
expect(content).toMatch(`maybe.value = count.value`)
|
||||||
// let: handle both cases
|
// let: handle both cases
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`_isRef(lett) ? lett.value = count.value : lett = count.value`
|
`_isRef(lett) ? lett.value = count.value : lett = count.value`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`_isRef(v) ? v.value += 1 : v += 1`)
|
expect(content).toMatch(`_isRef(v) ? v.value += 1 : v += 1`)
|
||||||
expect(content).toMatch(`_isRef(v) ? v.value -= 1 : v -= 1`)
|
expect(content).toMatch(`_isRef(v) ? v.value -= 1 : v -= 1`)
|
||||||
|
@ -780,7 +780,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
<div @click="--lett"/>
|
<div @click="--lett"/>
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
// known const ref: set value
|
// known const ref: set value
|
||||||
expect(content).toMatch(`count.value++`)
|
expect(content).toMatch(`count.value++`)
|
||||||
|
@ -809,7 +809,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
<div @click="({ lett } = val)"/>
|
<div @click="({ lett } = val)"/>
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ inlineTemplate: true }
|
{ inlineTemplate: true },
|
||||||
)
|
)
|
||||||
// known const ref: set value
|
// known const ref: set value
|
||||||
expect(content).toMatch(`({ count: count.value } = val)`)
|
expect(content).toMatch(`({ count: count.value } = val)`)
|
||||||
|
@ -840,9 +840,9 @@ describe('SFC compile <script setup>', () => {
|
||||||
{
|
{
|
||||||
inlineTemplate: true,
|
inlineTemplate: true,
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
ssr: true
|
ssr: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`\n __ssrInlineRender: true,\n`)
|
expect(content).toMatch(`\n __ssrInlineRender: true,\n`)
|
||||||
expect(content).toMatch(`return (_ctx, _push`)
|
expect(content).toMatch(`return (_ctx, _push`)
|
||||||
|
@ -866,9 +866,9 @@ describe('SFC compile <script setup>', () => {
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
inlineTemplate: false
|
inlineTemplate: false,
|
||||||
}
|
},
|
||||||
)
|
),
|
||||||
).not.toThrowError()
|
).not.toThrowError()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -887,11 +887,11 @@ describe('SFC compile <script setup>', () => {
|
||||||
const { content, bindings } = compile(
|
const { content, bindings } = compile(
|
||||||
`<script setup lang="ts">
|
`<script setup lang="ts">
|
||||||
enum Foo { A = 123 }
|
enum Foo { A = 123 }
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
Foo: BindingTypes.LITERAL_CONST
|
Foo: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -904,14 +904,14 @@ describe('SFC compile <script setup>', () => {
|
||||||
</script>
|
</script>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
enum Foo { A = 123 }
|
enum Foo { A = 123 }
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
D: BindingTypes.LITERAL_CONST,
|
D: BindingTypes.LITERAL_CONST,
|
||||||
C: BindingTypes.LITERAL_CONST,
|
C: BindingTypes.LITERAL_CONST,
|
||||||
B: BindingTypes.LITERAL_CONST,
|
B: BindingTypes.LITERAL_CONST,
|
||||||
Foo: BindingTypes.LITERAL_CONST
|
Foo: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -920,11 +920,11 @@ describe('SFC compile <script setup>', () => {
|
||||||
`<script setup lang="ts">
|
`<script setup lang="ts">
|
||||||
const enum Foo { A = 123 }
|
const enum Foo { A = 123 }
|
||||||
</script>`,
|
</script>`,
|
||||||
{ hoistStatic: true }
|
{ hoistStatic: true },
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
Foo: BindingTypes.LITERAL_CONST
|
Foo: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -933,7 +933,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
`<script setup lang="ts">
|
`<script setup lang="ts">
|
||||||
import type { Foo } from './main.ts'
|
import type { Foo } from './main.ts'
|
||||||
import { type Bar, Baz } from './main.ts'
|
import { type Bar, Baz } from './main.ts'
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`return { get Baz() { return Baz } }`)
|
expect(content).toMatch(`return { get Baz() { return Baz } }`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
|
@ -1057,7 +1057,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
// class method
|
// class method
|
||||||
assertAwaitDetection(
|
assertAwaitDetection(
|
||||||
`const cls = class Foo { async method() { await bar }}`,
|
`const cls = class Foo { async method() { await bar }}`,
|
||||||
false
|
false,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1065,7 +1065,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
describe('errors', () => {
|
describe('errors', () => {
|
||||||
test('<script> and <script setup> must have same lang', () => {
|
test('<script> and <script setup> must have same lang', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(`<script>foo()</script><script setup lang="ts">bar()</script>`)
|
compile(`<script>foo()</script><script setup lang="ts">bar()</script>`),
|
||||||
).toThrow(`<script> and <script setup> must have the same language type`)
|
).toThrow(`<script> and <script setup> must have the same language type`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1075,20 +1075,20 @@ describe('SFC compile <script setup>', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(`<script setup>
|
compile(`<script setup>
|
||||||
export const a = 1
|
export const a = 1
|
||||||
</script>`)
|
</script>`),
|
||||||
).toThrow(moduleErrorMsg)
|
).toThrow(moduleErrorMsg)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(`<script setup>
|
compile(`<script setup>
|
||||||
export * from './foo'
|
export * from './foo'
|
||||||
</script>`)
|
</script>`),
|
||||||
).toThrow(moduleErrorMsg)
|
).toThrow(moduleErrorMsg)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(`<script setup>
|
compile(`<script setup>
|
||||||
const bar = 1
|
const bar = 1
|
||||||
export { bar as default }
|
export { bar as default }
|
||||||
</script>`)
|
</script>`),
|
||||||
).toThrow(moduleErrorMsg)
|
).toThrow(moduleErrorMsg)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1101,14 +1101,14 @@ describe('SFC compile <script setup>', () => {
|
||||||
default: () => bar
|
default: () => bar
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>`)
|
</script>`),
|
||||||
).toThrow(`cannot reference locally declared variables`)
|
).toThrow(`cannot reference locally declared variables`)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(`<script setup>
|
compile(`<script setup>
|
||||||
let bar = 'hello'
|
let bar = 'hello'
|
||||||
defineEmits([bar])
|
defineEmits([bar])
|
||||||
</script>`)
|
</script>`),
|
||||||
).toThrow(`cannot reference locally declared variables`)
|
).toThrow(`cannot reference locally declared variables`)
|
||||||
|
|
||||||
// #4644
|
// #4644
|
||||||
|
@ -1121,7 +1121,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
default: () => bar
|
default: () => bar
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>`)
|
</script>`),
|
||||||
).not.toThrow(`cannot reference locally declared variables`)
|
).not.toThrow(`cannot reference locally declared variables`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1137,7 +1137,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
defineEmits({
|
defineEmits({
|
||||||
foo: bar => bar > 1
|
foo: bar => bar > 1
|
||||||
})
|
})
|
||||||
</script>`).content
|
</script>`).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1153,7 +1153,7 @@ describe('SFC compile <script setup>', () => {
|
||||||
defineEmits({
|
defineEmits({
|
||||||
foo: () => bar > 1
|
foo: () => bar > 1
|
||||||
})
|
})
|
||||||
</script>`).content
|
</script>`).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1187,7 +1187,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.PROPS
|
bar: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
expect(bindings!.__isScriptSetup).toBe(false)
|
expect(bindings!.__isScriptSetup).toBe(false)
|
||||||
})
|
})
|
||||||
|
@ -1211,7 +1211,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.PROPS,
|
bar: BindingTypes.PROPS,
|
||||||
baz: BindingTypes.PROPS,
|
baz: BindingTypes.PROPS,
|
||||||
qux: BindingTypes.PROPS
|
qux: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
expect(bindings!.__isScriptSetup).toBe(false)
|
expect(bindings!.__isScriptSetup).toBe(false)
|
||||||
})
|
})
|
||||||
|
@ -1232,7 +1232,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.SETUP_MAYBE_REF,
|
foo: BindingTypes.SETUP_MAYBE_REF,
|
||||||
bar: BindingTypes.SETUP_MAYBE_REF
|
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||||
})
|
})
|
||||||
expect(bindings!.__isScriptSetup).toBe(false)
|
expect(bindings!.__isScriptSetup).toBe(false)
|
||||||
})
|
})
|
||||||
|
@ -1247,7 +1247,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
</script>
|
</script>
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.LITERAL_CONST
|
foo: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1267,7 +1267,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.SETUP_MAYBE_REF,
|
foo: BindingTypes.SETUP_MAYBE_REF,
|
||||||
bar: BindingTypes.SETUP_MAYBE_REF
|
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||||
})
|
})
|
||||||
expect(bindings!.__isScriptSetup).toBe(false)
|
expect(bindings!.__isScriptSetup).toBe(false)
|
||||||
})
|
})
|
||||||
|
@ -1288,7 +1288,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.DATA,
|
foo: BindingTypes.DATA,
|
||||||
bar: BindingTypes.DATA
|
bar: BindingTypes.DATA,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1321,7 +1321,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.OPTIONS,
|
foo: BindingTypes.OPTIONS,
|
||||||
bar: BindingTypes.OPTIONS
|
bar: BindingTypes.OPTIONS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1335,7 +1335,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.OPTIONS,
|
foo: BindingTypes.OPTIONS,
|
||||||
bar: BindingTypes.OPTIONS
|
bar: BindingTypes.OPTIONS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1352,7 +1352,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.OPTIONS,
|
foo: BindingTypes.OPTIONS,
|
||||||
bar: BindingTypes.OPTIONS
|
bar: BindingTypes.OPTIONS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1389,7 +1389,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
baz: BindingTypes.SETUP_MAYBE_REF,
|
baz: BindingTypes.SETUP_MAYBE_REF,
|
||||||
qux: BindingTypes.DATA,
|
qux: BindingTypes.DATA,
|
||||||
quux: BindingTypes.OPTIONS,
|
quux: BindingTypes.OPTIONS,
|
||||||
quuz: BindingTypes.OPTIONS
|
quuz: BindingTypes.OPTIONS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1416,7 +1416,7 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
c: BindingTypes.LITERAL_CONST,
|
c: BindingTypes.LITERAL_CONST,
|
||||||
d: BindingTypes.SETUP_MAYBE_REF,
|
d: BindingTypes.SETUP_MAYBE_REF,
|
||||||
e: BindingTypes.SETUP_LET,
|
e: BindingTypes.SETUP_LET,
|
||||||
foo: BindingTypes.PROPS
|
foo: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1427,8 +1427,8 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
<template>{{ a }}</template>`,
|
<template>{{ a }}</template>`,
|
||||||
undefined,
|
undefined,
|
||||||
{
|
{
|
||||||
filename: 'FooBar.vue'
|
filename: 'FooBar.vue',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`export default {
|
expect(content).toMatch(`export default {
|
||||||
__name: 'FooBar'`)
|
__name: 'FooBar'`)
|
||||||
|
@ -1446,8 +1446,8 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
<template>{{ a }}</template>`,
|
<template>{{ a }}</template>`,
|
||||||
undefined,
|
undefined,
|
||||||
{
|
{
|
||||||
filename: 'FooBar.vue'
|
filename: 'FooBar.vue',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch(`name: 'FooBar'`)
|
expect(content).not.toMatch(`name: 'FooBar'`)
|
||||||
expect(content).toMatch(`name: 'Baz'`)
|
expect(content).toMatch(`name: 'Baz'`)
|
||||||
|
@ -1466,8 +1466,8 @@ describe('SFC analyze <script> bindings', () => {
|
||||||
<template>{{ a }}</template>`,
|
<template>{{ a }}</template>`,
|
||||||
undefined,
|
undefined,
|
||||||
{
|
{
|
||||||
filename: 'FooBar.vue'
|
filename: 'FooBar.vue',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch(`name: 'FooBar'`)
|
expect(content).not.toMatch(`name: 'FooBar'`)
|
||||||
expect(content).toMatch(`name: 'Baz'`)
|
expect(content).toMatch(`name: 'Baz'`)
|
||||||
|
@ -1483,8 +1483,8 @@ describe('SFC genDefaultAs', () => {
|
||||||
export default {}
|
export default {}
|
||||||
</script>`,
|
</script>`,
|
||||||
{
|
{
|
||||||
genDefaultAs: '_sfc_'
|
genDefaultAs: '_sfc_',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch('export default')
|
expect(content).not.toMatch('export default')
|
||||||
expect(content).toMatch(`const _sfc_ = {}`)
|
expect(content).toMatch(`const _sfc_ = {}`)
|
||||||
|
@ -1500,8 +1500,8 @@ describe('SFC genDefaultAs', () => {
|
||||||
.foo { color: v-bind(x) }
|
.foo { color: v-bind(x) }
|
||||||
</style>`,
|
</style>`,
|
||||||
{
|
{
|
||||||
genDefaultAs: '_sfc_'
|
genDefaultAs: '_sfc_',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch('export default')
|
expect(content).not.toMatch('export default')
|
||||||
expect(content).not.toMatch('__default__')
|
expect(content).not.toMatch('__default__')
|
||||||
|
@ -1518,12 +1518,12 @@ describe('SFC genDefaultAs', () => {
|
||||||
const a = 1
|
const a = 1
|
||||||
</script>`,
|
</script>`,
|
||||||
{
|
{
|
||||||
genDefaultAs: '_sfc_'
|
genDefaultAs: '_sfc_',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch('export default')
|
expect(content).not.toMatch('export default')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`
|
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -1537,12 +1537,12 @@ describe('SFC genDefaultAs', () => {
|
||||||
const a = 1
|
const a = 1
|
||||||
</script>`,
|
</script>`,
|
||||||
{
|
{
|
||||||
genDefaultAs: '_sfc_'
|
genDefaultAs: '_sfc_',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch('export default')
|
expect(content).not.toMatch('export default')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`
|
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -1553,8 +1553,8 @@ describe('SFC genDefaultAs', () => {
|
||||||
const a = 1
|
const a = 1
|
||||||
</script>`,
|
</script>`,
|
||||||
{
|
{
|
||||||
genDefaultAs: '_sfc_'
|
genDefaultAs: '_sfc_',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch('export default')
|
expect(content).not.toMatch('export default')
|
||||||
expect(content).toMatch(`const _sfc_ = {\n setup`)
|
expect(content).toMatch(`const _sfc_ = {\n setup`)
|
||||||
|
@ -1567,8 +1567,8 @@ describe('SFC genDefaultAs', () => {
|
||||||
const a = 1
|
const a = 1
|
||||||
</script>`,
|
</script>`,
|
||||||
{
|
{
|
||||||
genDefaultAs: '_sfc_'
|
genDefaultAs: '_sfc_',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch('export default')
|
expect(content).not.toMatch('export default')
|
||||||
expect(content).toMatch(`const _sfc_ = /*#__PURE__*/_defineComponent(`)
|
expect(content).toMatch(`const _sfc_ = /*#__PURE__*/_defineComponent(`)
|
||||||
|
@ -1584,12 +1584,12 @@ describe('SFC genDefaultAs', () => {
|
||||||
const a = 1
|
const a = 1
|
||||||
</script>`,
|
</script>`,
|
||||||
{
|
{
|
||||||
genDefaultAs: '_sfc_'
|
genDefaultAs: '_sfc_',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch('export default')
|
expect(content).not.toMatch('export default')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`const _sfc_ = /*#__PURE__*/_defineComponent({\n ...__default__`
|
`const _sfc_ = /*#__PURE__*/_defineComponent({\n ...__default__`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -1600,12 +1600,12 @@ describe('SFC genDefaultAs', () => {
|
||||||
import { toRef } from 'vue'
|
import { toRef } from 'vue'
|
||||||
const props = defineProps<{foo: string}>()
|
const props = defineProps<{foo: string}>()
|
||||||
const foo = toRef(() => props.foo)
|
const foo = toRef(() => props.foo)
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
toRef: BindingTypes.SETUP_CONST,
|
toRef: BindingTypes.SETUP_CONST,
|
||||||
props: BindingTypes.SETUP_REACTIVE_CONST,
|
props: BindingTypes.SETUP_REACTIVE_CONST,
|
||||||
foo: BindingTypes.SETUP_REF
|
foo: BindingTypes.SETUP_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1622,7 +1622,7 @@ describe('SFC genDefaultAs', () => {
|
||||||
compile(`
|
compile(`
|
||||||
<script setup>
|
<script setup>
|
||||||
import { foo } from './foo.js' assert { type: 'foobar' }
|
import { foo } from './foo.js' assert { type: 'foobar' }
|
||||||
</script>`)
|
</script>`),
|
||||||
).toThrow()
|
).toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1635,9 +1635,9 @@ describe('SFC genDefaultAs', () => {
|
||||||
`,
|
`,
|
||||||
{
|
{
|
||||||
babelParserPlugins: [
|
babelParserPlugins: [
|
||||||
['importAttributes', { deprecatedAssertSyntax: true }]
|
['importAttributes', { deprecatedAssertSyntax: true }],
|
||||||
]
|
],
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BindingTypes } from '@vue/compiler-core'
|
import { BindingTypes } from '@vue/compiler-core'
|
||||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||||
|
|
||||||
describe('defineEmits', () => {
|
describe('defineEmits', () => {
|
||||||
test('basic usage', () => {
|
test('basic usage', () => {
|
||||||
|
@ -10,13 +10,13 @@ const myEmit = defineEmits(['foo', 'bar'])
|
||||||
`)
|
`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
myEmit: BindingTypes.SETUP_CONST
|
myEmit: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
// should remove defineEmits import and call
|
// should remove defineEmits import and call
|
||||||
expect(content).not.toMatch('defineEmits')
|
expect(content).not.toMatch('defineEmits')
|
||||||
// should generate correct setup signature
|
// should generate correct setup signature
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`setup(__props, { expose: __expose, emit: __emit }) {`
|
`setup(__props, { expose: __expose, emit: __emit }) {`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch('const myEmit = __emit')
|
expect(content).toMatch('const myEmit = __emit')
|
||||||
// should include context options in default export
|
// should include context options in default export
|
||||||
|
@ -226,9 +226,9 @@ const emit = defineEmits(['a', 'b'])
|
||||||
foo: []
|
foo: []
|
||||||
(e: 'hi'): void
|
(e: 'hi'): void
|
||||||
}>()
|
}>()
|
||||||
</script>`)
|
</script>`),
|
||||||
).toThrow(
|
).toThrow(
|
||||||
`defineEmits() type cannot mixed call signature and property syntax.`
|
`defineEmits() type cannot mixed call signature and property syntax.`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||||
|
|
||||||
test('defineExpose()', () => {
|
test('defineExpose()', () => {
|
||||||
const { content } = compile(`
|
const { content } = compile(`
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BindingTypes } from '@vue/compiler-core'
|
import { BindingTypes } from '@vue/compiler-core'
|
||||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||||
|
|
||||||
describe('defineModel()', () => {
|
describe('defineModel()', () => {
|
||||||
test('basic usage', () => {
|
test('basic usage', () => {
|
||||||
|
@ -10,7 +10,7 @@ describe('defineModel()', () => {
|
||||||
const c = defineModel('count')
|
const c = defineModel('count')
|
||||||
const toString = defineModel('toString', { type: Function })
|
const toString = defineModel('toString', { type: Function })
|
||||||
</script>
|
</script>
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch('props: {')
|
expect(content).toMatch('props: {')
|
||||||
|
@ -18,10 +18,10 @@ describe('defineModel()', () => {
|
||||||
expect(content).toMatch('"count": {},')
|
expect(content).toMatch('"count": {},')
|
||||||
expect(content).toMatch('"toString": { type: Function },')
|
expect(content).toMatch('"toString": { type: Function },')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
'emits: ["update:modelValue", "update:count", "update:toString"],'
|
'emits: ["update:modelValue", "update:count", "update:toString"],',
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`const modelValue = _useModel(__props, "modelValue")`
|
`const modelValue = _useModel(__props, "modelValue")`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`const c = _useModel(__props, "count")`)
|
expect(content).toMatch(`const c = _useModel(__props, "count")`)
|
||||||
expect(content).toMatch(`return { modelValue, c, toString }`)
|
expect(content).toMatch(`return { modelValue, c, toString }`)
|
||||||
|
@ -31,7 +31,7 @@ describe('defineModel()', () => {
|
||||||
modelValue: BindingTypes.SETUP_REF,
|
modelValue: BindingTypes.SETUP_REF,
|
||||||
count: BindingTypes.PROPS,
|
count: BindingTypes.PROPS,
|
||||||
c: BindingTypes.SETUP_REF,
|
c: BindingTypes.SETUP_REF,
|
||||||
toString: BindingTypes.SETUP_REF
|
toString: BindingTypes.SETUP_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ describe('defineModel()', () => {
|
||||||
defineEmits(['change'])
|
defineEmits(['change'])
|
||||||
const count = defineModel({ default: 0 })
|
const count = defineModel({ default: 0 })
|
||||||
</script>
|
</script>
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels({ foo: String }`)
|
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels({ foo: String }`)
|
||||||
|
@ -53,7 +53,7 @@ describe('defineModel()', () => {
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
count: BindingTypes.SETUP_REF,
|
count: BindingTypes.SETUP_REF,
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
modelValue: BindingTypes.PROPS
|
modelValue: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ describe('defineModel()', () => {
|
||||||
defineProps(['foo', 'bar'])
|
defineProps(['foo', 'bar'])
|
||||||
const count = defineModel('count')
|
const count = defineModel('count')
|
||||||
</script>
|
</script>
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels(['foo', 'bar'], {
|
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels(['foo', 'bar'], {
|
||||||
|
@ -75,7 +75,7 @@ describe('defineModel()', () => {
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.PROPS,
|
bar: BindingTypes.PROPS,
|
||||||
count: BindingTypes.SETUP_REF
|
count: BindingTypes.SETUP_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ describe('defineModel()', () => {
|
||||||
|
|
||||||
const local = true
|
const local = true
|
||||||
const hoist = defineModel('hoist', { local })
|
const hoist = defineModel('hoist', { local })
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`_useModel(__props, "modelValue", { local: true })`)
|
expect(content).toMatch(`_useModel(__props, "modelValue", { local: true })`)
|
||||||
|
@ -111,21 +111,21 @@ describe('defineModel()', () => {
|
||||||
const disabled = defineModel<number>('disabled', { required: false })
|
const disabled = defineModel<number>('disabled', { required: false })
|
||||||
const any = defineModel<any | boolean>('any')
|
const any = defineModel<any | boolean>('any')
|
||||||
</script>
|
</script>
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch('"modelValue": { type: [Boolean, String] }')
|
expect(content).toMatch('"modelValue": { type: [Boolean, String] }')
|
||||||
expect(content).toMatch('"count": { type: Number }')
|
expect(content).toMatch('"count": { type: Number }')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
'"disabled": { type: Number, ...{ required: false } }'
|
'"disabled": { type: Number, ...{ required: false } }',
|
||||||
)
|
)
|
||||||
expect(content).toMatch('"any": { type: Boolean, skipCheck: true }')
|
expect(content).toMatch('"any": { type: Boolean, skipCheck: true }')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
'emits: ["update:modelValue", "update:count", "update:disabled", "update:any"]'
|
'emits: ["update:modelValue", "update:count", "update:disabled", "update:any"]',
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`const modelValue = _useModel(__props, "modelValue")`
|
`const modelValue = _useModel(__props, "modelValue")`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`const count = _useModel(__props, "count")`)
|
expect(content).toMatch(`const count = _useModel(__props, "count")`)
|
||||||
expect(content).toMatch(`const disabled = _useModel(__props, "disabled")`)
|
expect(content).toMatch(`const disabled = _useModel(__props, "disabled")`)
|
||||||
|
@ -135,7 +135,7 @@ describe('defineModel()', () => {
|
||||||
modelValue: BindingTypes.SETUP_REF,
|
modelValue: BindingTypes.SETUP_REF,
|
||||||
count: BindingTypes.SETUP_REF,
|
count: BindingTypes.SETUP_REF,
|
||||||
disabled: BindingTypes.SETUP_REF,
|
disabled: BindingTypes.SETUP_REF,
|
||||||
any: BindingTypes.SETUP_REF
|
any: BindingTypes.SETUP_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -150,21 +150,21 @@ describe('defineModel()', () => {
|
||||||
const optional = defineModel<string>('optional', { required: false })
|
const optional = defineModel<string>('optional', { required: false })
|
||||||
</script>
|
</script>
|
||||||
`,
|
`,
|
||||||
{ isProd: true }
|
{ isProd: true },
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch('"modelValue": { type: Boolean }')
|
expect(content).toMatch('"modelValue": { type: Boolean }')
|
||||||
expect(content).toMatch('"fn": {}')
|
expect(content).toMatch('"fn": {}')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
'"fnWithDefault": { type: Function, ...{ default: () => null } },'
|
'"fnWithDefault": { type: Function, ...{ default: () => null } },',
|
||||||
)
|
)
|
||||||
expect(content).toMatch('"str": {}')
|
expect(content).toMatch('"str": {}')
|
||||||
expect(content).toMatch('"optional": { required: false }')
|
expect(content).toMatch('"optional": { required: false }')
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
'emits: ["update:modelValue", "update:fn", "update:fnWithDefault", "update:str", "update:optional"]'
|
'emits: ["update:modelValue", "update:fn", "update:fnWithDefault", "update:str", "update:optional"]',
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`const modelValue = _useModel(__props, "modelValue")`
|
`const modelValue = _useModel(__props, "modelValue")`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`const fn = _useModel(__props, "fn")`)
|
expect(content).toMatch(`const fn = _useModel(__props, "fn")`)
|
||||||
expect(content).toMatch(`const str = _useModel(__props, "str")`)
|
expect(content).toMatch(`const str = _useModel(__props, "str")`)
|
||||||
|
@ -173,7 +173,7 @@ describe('defineModel()', () => {
|
||||||
fn: BindingTypes.SETUP_REF,
|
fn: BindingTypes.SETUP_REF,
|
||||||
fnWithDefault: BindingTypes.SETUP_REF,
|
fnWithDefault: BindingTypes.SETUP_REF,
|
||||||
str: BindingTypes.SETUP_REF,
|
str: BindingTypes.SETUP_REF,
|
||||||
optional: BindingTypes.SETUP_REF
|
optional: BindingTypes.SETUP_REF,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||||
|
|
||||||
describe('defineOptions()', () => {
|
describe('defineOptions()', () => {
|
||||||
test('basic usage', () => {
|
test('basic usage', () => {
|
||||||
|
@ -12,7 +12,7 @@ describe('defineOptions()', () => {
|
||||||
expect(content).not.toMatch('defineOptions')
|
expect(content).not.toMatch('defineOptions')
|
||||||
// should include context options in default export
|
// should include context options in default export
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`export default /*#__PURE__*/Object.assign({ name: 'FooApp' }, `
|
`export default /*#__PURE__*/Object.assign({ name: 'FooApp' }, `,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ describe('defineOptions()', () => {
|
||||||
defineOptions({ name: 'FooApp' })
|
defineOptions({ name: 'FooApp' })
|
||||||
defineOptions({ name: 'BarApp' })
|
defineOptions({ name: 'BarApp' })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError('[@vue/compiler-sfc] duplicate defineOptions() call')
|
).toThrowError('[@vue/compiler-sfc] duplicate defineOptions() call')
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -45,9 +45,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({ props: { foo: String } })
|
defineOptions({ props: { foo: String } })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.',
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -55,9 +55,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({ emits: ['update'] })
|
defineOptions({ emits: ['update'] })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare emits. Use defineEmits() instead.'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare emits. Use defineEmits() instead.',
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -65,9 +65,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({ expose: ['foo'] })
|
defineOptions({ expose: ['foo'] })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare expose. Use defineExpose() instead.'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare expose. Use defineExpose() instead.',
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -75,9 +75,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({ slots: ['foo'] })
|
defineOptions({ slots: ['foo'] })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead.'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead.',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -87,9 +87,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions<{ name: 'FooApp' }>()
|
defineOptions<{ name: 'FooApp' }>()
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot accept type arguments'
|
'[@vue/compiler-sfc] defineOptions() cannot accept type arguments',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -99,9 +99,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({ props: [] } as any)
|
defineOptions({ props: [] } as any)
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead.',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -111,9 +111,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({ props: ['foo'] })
|
defineOptions({ props: ['foo'] })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare props. Use defineProps() instead',
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -121,9 +121,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({ emits: ['update'] })
|
defineOptions({ emits: ['update'] })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare emits. Use defineEmits() instead'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare emits. Use defineEmits() instead',
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -131,9 +131,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup>
|
<script setup>
|
||||||
defineOptions({ expose: ['foo'] })
|
defineOptions({ expose: ['foo'] })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare expose. Use defineExpose() instead'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare expose. Use defineExpose() instead',
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -141,9 +141,9 @@ describe('defineOptions()', () => {
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineOptions({ slots: Object })
|
defineOptions({ slots: Object })
|
||||||
</script>
|
</script>
|
||||||
`)
|
`),
|
||||||
).toThrowError(
|
).toThrowError(
|
||||||
'[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead'
|
'[@vue/compiler-sfc] defineOptions() cannot be used to declare slots. Use defineSlots() instead',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { BindingTypes } from '@vue/compiler-core'
|
import { BindingTypes } from '@vue/compiler-core'
|
||||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||||
|
|
||||||
describe('defineProps', () => {
|
describe('defineProps', () => {
|
||||||
test('basic usage', () => {
|
test('basic usage', () => {
|
||||||
|
@ -17,7 +17,7 @@ const bar = 1
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.LITERAL_CONST,
|
bar: BindingTypes.LITERAL_CONST,
|
||||||
props: BindingTypes.SETUP_REACTIVE_CONST
|
props: BindingTypes.SETUP_REACTIVE_CONST,
|
||||||
})
|
})
|
||||||
|
|
||||||
// should remove defineOptions import and call
|
// should remove defineOptions import and call
|
||||||
|
@ -146,11 +146,11 @@ const props = defineProps({ foo: String })
|
||||||
expect(content).toMatch(`symbol: { type: Symbol, required: true }`)
|
expect(content).toMatch(`symbol: { type: Symbol, required: true }`)
|
||||||
expect(content).toMatch(`error: { type: Error, required: true }`)
|
expect(content).toMatch(`error: { type: Error, required: true }`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`objectOrFn: { type: [Function, Object], required: true },`
|
`objectOrFn: { type: [Function, Object], required: true },`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`extract: { type: Number, required: true }`)
|
expect(content).toMatch(`extract: { type: Number, required: true }`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`exclude: { type: [Number, Boolean], required: true }`
|
`exclude: { type: [Number, Boolean], required: true }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`uppercase: { type: String, required: true }`)
|
expect(content).toMatch(`uppercase: { type: String, required: true }`)
|
||||||
expect(content).toMatch(`params: { type: Array, required: true }`)
|
expect(content).toMatch(`params: { type: Array, required: true }`)
|
||||||
|
@ -158,10 +158,10 @@ const props = defineProps({ foo: String })
|
||||||
expect(content).toMatch(`union: { type: [String, Number], required: true }`)
|
expect(content).toMatch(`union: { type: [String, Number], required: true }`)
|
||||||
expect(content).toMatch(`literalUnion: { type: String, required: true }`)
|
expect(content).toMatch(`literalUnion: { type: String, required: true }`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`literalUnionNumber: { type: Number, required: true }`
|
`literalUnionNumber: { type: Number, required: true }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`literalUnionMixed: { type: [String, Number, Boolean], required: true }`
|
`literalUnionMixed: { type: [String, Number, Boolean], required: true }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`intersection: { type: Object, required: true }`)
|
expect(content).toMatch(`intersection: { type: Object, required: true }`)
|
||||||
expect(content).toMatch(`intersection2: { type: String, required: true }`)
|
expect(content).toMatch(`intersection2: { type: String, required: true }`)
|
||||||
|
@ -171,13 +171,13 @@ const props = defineProps({ foo: String })
|
||||||
expect(content).toMatch(`unknownUnion: { type: null, required: true }`)
|
expect(content).toMatch(`unknownUnion: { type: null, required: true }`)
|
||||||
// intersection containing unknown type: narrow to the known types
|
// intersection containing unknown type: narrow to the known types
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`unknownIntersection: { type: Object, required: true },`
|
`unknownIntersection: { type: Object, required: true },`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },`
|
`unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }`
|
`unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }`,
|
||||||
)
|
)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
string: BindingTypes.PROPS,
|
string: BindingTypes.PROPS,
|
||||||
|
@ -218,7 +218,7 @@ const props = defineProps({ foo: String })
|
||||||
unknownUnion: BindingTypes.PROPS,
|
unknownUnion: BindingTypes.PROPS,
|
||||||
unknownIntersection: BindingTypes.PROPS,
|
unknownIntersection: BindingTypes.PROPS,
|
||||||
unknownUnionWithBoolean: BindingTypes.PROPS,
|
unknownUnionWithBoolean: BindingTypes.PROPS,
|
||||||
unknownUnionWithFunction: BindingTypes.PROPS
|
unknownUnionWithFunction: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -232,7 +232,7 @@ const props = defineProps({ foo: String })
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
x: BindingTypes.PROPS
|
x: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -257,7 +257,7 @@ const props = defineProps({ foo: String })
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
x: BindingTypes.PROPS,
|
x: BindingTypes.PROPS,
|
||||||
y: BindingTypes.PROPS,
|
y: BindingTypes.PROPS,
|
||||||
z: BindingTypes.PROPS
|
z: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -271,7 +271,7 @@ const props = defineProps({ foo: String })
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
x: BindingTypes.PROPS
|
x: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ const props = defineProps({ foo: String })
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
x: BindingTypes.PROPS
|
x: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -301,7 +301,7 @@ const props = defineProps({ foo: String })
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
x: BindingTypes.PROPS
|
x: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -315,7 +315,7 @@ const props = defineProps({ foo: String })
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
x: BindingTypes.PROPS
|
x: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ const props = defineProps({ foo: String })
|
||||||
expect(content).toMatch(`props: ['foo']`)
|
expect(content).toMatch(`props: ['foo']`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS
|
foo: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -354,21 +354,21 @@ const props = defineProps({ foo: String })
|
||||||
`)
|
`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`foo: { type: String, required: false, default: 'hi' }`
|
`foo: { type: String, required: false, default: 'hi' }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`bar: { type: Number, required: false }`)
|
expect(content).toMatch(`bar: { type: Number, required: false }`)
|
||||||
expect(content).toMatch(`baz: { type: Boolean, required: true }`)
|
expect(content).toMatch(`baz: { type: Boolean, required: true }`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`qux: { type: Function, required: false, default() { return 1 } }`
|
`qux: { type: Function, required: false, default() { return 1 } }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`quux: { type: Function, required: false, default() { } }`
|
`quux: { type: Function, required: false, default() { } }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } }`
|
`quuxx: { type: Promise, required: false, async default() { return await Promise.resolve('hi') } }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`fred: { type: String, required: false, get default() { return 'fred' } }`
|
`fred: { type: String, required: false, get default() { return 'fred' } }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`const props = __props`)
|
expect(content).toMatch(`const props = __props`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
|
@ -379,7 +379,7 @@ const props = defineProps({ foo: String })
|
||||||
quux: BindingTypes.PROPS,
|
quux: BindingTypes.PROPS,
|
||||||
quuxx: BindingTypes.PROPS,
|
quuxx: BindingTypes.PROPS,
|
||||||
fred: BindingTypes.PROPS,
|
fred: BindingTypes.PROPS,
|
||||||
props: BindingTypes.SETUP_CONST
|
props: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -415,7 +415,7 @@ const props = defineProps({ foo: String })
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
`,
|
`,
|
||||||
{ isProd: true }
|
{ isProd: true },
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`const props = __props`)
|
expect(content).toMatch(`const props = __props`)
|
||||||
|
@ -446,7 +446,7 @@ const props = defineProps({ foo: String })
|
||||||
foo: { type: String, required: false },
|
foo: { type: String, required: false },
|
||||||
bar: { type: Number, required: false },
|
bar: { type: Number, required: false },
|
||||||
baz: { type: Boolean, required: true }
|
baz: { type: Boolean, required: true }
|
||||||
}, { ...defaults })`.trim()
|
}, { ...defaults })`.trim(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -469,7 +469,7 @@ const props = defineProps({ foo: String })
|
||||||
foo: { type: String, required: false },
|
foo: { type: String, required: false },
|
||||||
bar: { type: Number, required: false },
|
bar: { type: Number, required: false },
|
||||||
baz: { type: Boolean, required: true }
|
baz: { type: Boolean, required: true }
|
||||||
}, defaults)`.trim()
|
}, defaults)`.trim(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -487,7 +487,7 @@ const props = defineProps({ foo: String })
|
||||||
}>(), { ...defaults })
|
}>(), { ...defaults })
|
||||||
</script>
|
</script>
|
||||||
`,
|
`,
|
||||||
{ isProd: true }
|
{ isProd: true },
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
|
expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
|
||||||
|
@ -498,7 +498,7 @@ const props = defineProps({ foo: String })
|
||||||
bar: { type: Boolean },
|
bar: { type: Boolean },
|
||||||
baz: { type: [Boolean, Function] },
|
baz: { type: [Boolean, Function] },
|
||||||
qux: {}
|
qux: {}
|
||||||
}, { ...defaults })`.trim()
|
}, { ...defaults })`.trim(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -520,7 +520,7 @@ const props = defineProps({ foo: String })
|
||||||
foo: { type: Function, required: false }
|
foo: { type: Function, required: false }
|
||||||
}, {
|
}, {
|
||||||
['fo' + 'o']() { return 'foo' }
|
['fo' + 'o']() { return 'foo' }
|
||||||
})`.trim()
|
})`.trim(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -533,8 +533,8 @@ const props = defineProps({ foo: String })
|
||||||
foo: Foo
|
foo: Foo
|
||||||
}>()
|
}>()
|
||||||
</script>`,
|
</script>`,
|
||||||
{ hoistStatic: true }
|
{ hoistStatic: true },
|
||||||
).content
|
).content,
|
||||||
).toMatch(`foo: { type: Number`)
|
).toMatch(`foo: { type: Number`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -545,8 +545,8 @@ const props = defineProps({ foo: String })
|
||||||
foo: Foo
|
foo: Foo
|
||||||
}>()
|
}>()
|
||||||
</script>`,
|
</script>`,
|
||||||
{ hoistStatic: true }
|
{ hoistStatic: true },
|
||||||
).content
|
).content,
|
||||||
).toMatch(`foo: { type: String`)
|
).toMatch(`foo: { type: String`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -557,8 +557,8 @@ const props = defineProps({ foo: String })
|
||||||
foo: Foo
|
foo: Foo
|
||||||
}>()
|
}>()
|
||||||
</script>`,
|
</script>`,
|
||||||
{ hoistStatic: true }
|
{ hoistStatic: true },
|
||||||
).content
|
).content,
|
||||||
).toMatch(`foo: { type: [String, Number]`)
|
).toMatch(`foo: { type: [String, Number]`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
|
@ -569,8 +569,8 @@ const props = defineProps({ foo: String })
|
||||||
foo: Foo
|
foo: Foo
|
||||||
}>()
|
}>()
|
||||||
</script>`,
|
</script>`,
|
||||||
{ hoistStatic: true }
|
{ hoistStatic: true },
|
||||||
).content
|
).content,
|
||||||
).toMatch(`foo: { type: Number`)
|
).toMatch(`foo: { type: Number`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -585,7 +585,7 @@ const props = defineProps({ foo: String })
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
bar: BindingTypes.SETUP_REF,
|
bar: BindingTypes.SETUP_REF,
|
||||||
computed: BindingTypes.SETUP_CONST
|
computed: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -596,7 +596,7 @@ const props = defineProps({ foo: String })
|
||||||
const { foo } = defineProps<{
|
const { foo } = defineProps<{
|
||||||
foo: Foo
|
foo: Foo
|
||||||
}>()
|
}>()
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`const { foo } = __props`)
|
expect(content).toMatch(`const { foo } = __props`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
|
@ -649,7 +649,7 @@ const props = defineProps({ foo: String })
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(content).toMatch(`"spa ce": { type: null, required: true }`)
|
expect(content).toMatch(`"spa ce": { type: null, required: true }`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`"exclamation!mark": { type: null, required: true }`
|
`"exclamation!mark": { type: null, required: true }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`"double\\"quote": { type: null, required: true }`)
|
expect(content).toMatch(`"double\\"quote": { type: null, required: true }`)
|
||||||
expect(content).toMatch(`"hash#tag": { type: null, required: true }`)
|
expect(content).toMatch(`"hash#tag": { type: null, required: true }`)
|
||||||
|
@ -670,7 +670,7 @@ const props = defineProps({ foo: String })
|
||||||
expect(content).toMatch(`"question?mark": { type: null, required: true }`)
|
expect(content).toMatch(`"question?mark": { type: null, required: true }`)
|
||||||
expect(content).toMatch(`"at@sign": { type: null, required: true }`)
|
expect(content).toMatch(`"at@sign": { type: null, required: true }`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`"square[brack]ets": { type: null, required: true }`
|
`"square[brack]ets": { type: null, required: true }`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`"back\\\\slash": { type: null, required: true }`)
|
expect(content).toMatch(`"back\\\\slash": { type: null, required: true }`)
|
||||||
expect(content).toMatch(`"ca^ret": { type: null, required: true }`)
|
expect(content).toMatch(`"ca^ret": { type: null, required: true }`)
|
||||||
|
@ -707,7 +707,7 @@ const props = defineProps({ foo: String })
|
||||||
'curly{bra}ces': BindingTypes.PROPS,
|
'curly{bra}ces': BindingTypes.PROPS,
|
||||||
'pi|pe': BindingTypes.PROPS,
|
'pi|pe': BindingTypes.PROPS,
|
||||||
'til~de': BindingTypes.PROPS,
|
'til~de': BindingTypes.PROPS,
|
||||||
'da-sh': BindingTypes.PROPS
|
'da-sh': BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -718,7 +718,7 @@ const props = defineProps({ foo: String })
|
||||||
const props = defineProps<{ foo: number}>()
|
const props = defineProps<{ foo: number}>()
|
||||||
</script>`,
|
</script>`,
|
||||||
{ isProd: true, customElement: filename => /\.ce\.vue$/.test(filename) },
|
{ isProd: true, customElement: filename => /\.ce\.vue$/.test(filename) },
|
||||||
{ filename: 'app.ce.vue' }
|
{ filename: 'app.ce.vue' },
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(content).toMatch(`foo: {type: Number}`)
|
expect(content).toMatch(`foo: {type: Number}`)
|
||||||
|
@ -736,7 +736,7 @@ const props = defineProps({ foo: String })
|
||||||
});
|
});
|
||||||
</script>`,
|
</script>`,
|
||||||
{ isProd: true, customElement: filename => /\.ce\.vue$/.test(filename) },
|
{ isProd: true, customElement: filename => /\.ce\.vue$/.test(filename) },
|
||||||
{ filename: 'app.ce.vue' }
|
{ filename: 'app.ce.vue' },
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`foo: { default: 5.5, type: Number }`)
|
expect(content).toMatch(`foo: { default: 5.5, type: Number }`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { BindingTypes } from '@vue/compiler-core'
|
import { BindingTypes } from '@vue/compiler-core'
|
||||||
import { SFCScriptCompileOptions } from '../../src'
|
import type { SFCScriptCompileOptions } from '../../src'
|
||||||
import { compileSFCScript, assertCode } from '../utils'
|
import { assertCode, compileSFCScript } from '../utils'
|
||||||
|
|
||||||
describe('sfc reactive props destructure', () => {
|
describe('sfc reactive props destructure', () => {
|
||||||
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
||||||
return compileSFCScript(src, {
|
return compileSFCScript(src, {
|
||||||
inlineTemplate: true,
|
inlineTemplate: true,
|
||||||
propsDestructure: true,
|
propsDestructure: true,
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ describe('sfc reactive props destructure', () => {
|
||||||
expect(content).toMatch(`_toDisplayString(__props.foo)`)
|
expect(content).toMatch(`_toDisplayString(__props.foo)`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS
|
foo: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ describe('sfc reactive props destructure', () => {
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.LITERAL_CONST,
|
bar: BindingTypes.LITERAL_CONST,
|
||||||
hello: BindingTypes.LITERAL_CONST
|
hello: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ describe('sfc reactive props destructure', () => {
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.PROPS,
|
bar: BindingTypes.PROPS,
|
||||||
test: BindingTypes.SETUP_CONST
|
test: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -115,11 +115,11 @@ describe('sfc reactive props destructure', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
__propsAliases: {
|
__propsAliases: {
|
||||||
fooBar: 'foo:bar'
|
fooBar: 'foo:bar',
|
||||||
},
|
},
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
'foo:bar': BindingTypes.PROPS,
|
'foo:bar': BindingTypes.PROPS,
|
||||||
fooBar: BindingTypes.PROPS_ALIASED
|
fooBar: BindingTypes.PROPS_ALIASED,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(content).toMatch(`
|
expect(content).toMatch(`
|
||||||
|
@ -159,13 +159,13 @@ describe('sfc reactive props destructure', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
__propsAliases: {
|
__propsAliases: {
|
||||||
fooBar: 'foo:bar'
|
fooBar: 'foo:bar',
|
||||||
},
|
},
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.PROPS,
|
bar: BindingTypes.PROPS,
|
||||||
'foo:bar': BindingTypes.PROPS,
|
'foo:bar': BindingTypes.PROPS,
|
||||||
fooBar: BindingTypes.PROPS_ALIASED,
|
fooBar: BindingTypes.PROPS_ALIASED,
|
||||||
'onUpdate:modelValue': BindingTypes.PROPS
|
'onUpdate:modelValue': BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
expect(content).toMatch(`
|
expect(content).toMatch(`
|
||||||
props: {
|
props: {
|
||||||
|
@ -184,7 +184,7 @@ describe('sfc reactive props destructure', () => {
|
||||||
const { foo = 1, bar = {}, func = () => {} } = defineProps<{ foo?: number, bar?: object, baz?: any, boola?: boolean, boolb?: boolean | number, func?: Function }>()
|
const { foo = 1, bar = {}, func = () => {} } = defineProps<{ foo?: number, bar?: object, baz?: any, boola?: boolean, boolb?: boolean | number, func?: Function }>()
|
||||||
</script>
|
</script>
|
||||||
`,
|
`,
|
||||||
{ isProd: true }
|
{ isProd: true },
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
// literals can be used as-is, non-literals are always returned from a
|
// literals can be used as-is, non-literals are always returned from a
|
||||||
|
@ -220,8 +220,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.PROPS_ALIASED,
|
bar: BindingTypes.PROPS_ALIASED,
|
||||||
__propsAliases: {
|
__propsAliases: {
|
||||||
bar: 'foo'
|
bar: 'foo',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -242,8 +242,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
'foo.bar': BindingTypes.PROPS,
|
'foo.bar': BindingTypes.PROPS,
|
||||||
fooBar: BindingTypes.PROPS_ALIASED,
|
fooBar: BindingTypes.PROPS_ALIASED,
|
||||||
__propsAliases: {
|
__propsAliases: {
|
||||||
fooBar: 'foo.bar'
|
fooBar: 'foo.bar',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -254,14 +254,14 @@ describe('sfc reactive props destructure', () => {
|
||||||
</script>
|
</script>
|
||||||
`)
|
`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`const rest = _createPropsRestProxy(__props, ["foo","bar"])`
|
`const rest = _createPropsRestProxy(__props, ["foo","bar"])`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
bar: BindingTypes.PROPS,
|
bar: BindingTypes.PROPS,
|
||||||
baz: BindingTypes.PROPS,
|
baz: BindingTypes.PROPS,
|
||||||
rest: BindingTypes.SETUP_REACTIVE_CONST
|
rest: BindingTypes.SETUP_REACTIVE_CONST,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ describe('sfc reactive props destructure', () => {
|
||||||
expect(content).toMatch(`_toDisplayString(__props.foo)`)
|
expect(content).toMatch(`_toDisplayString(__props.foo)`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS
|
foo: BindingTypes.PROPS,
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -339,22 +339,22 @@ describe('sfc reactive props destructure', () => {
|
||||||
test('should error on deep destructure', () => {
|
test('should error on deep destructure', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(
|
compile(
|
||||||
`<script setup>const { foo: [bar] } = defineProps(['foo'])</script>`
|
`<script setup>const { foo: [bar] } = defineProps(['foo'])</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`destructure does not support nested patterns`)
|
).toThrow(`destructure does not support nested patterns`)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(
|
compile(
|
||||||
`<script setup>const { foo: { bar } } = defineProps(['foo'])</script>`
|
`<script setup>const { foo: { bar } } = defineProps(['foo'])</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`destructure does not support nested patterns`)
|
).toThrow(`destructure does not support nested patterns`)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should error on computed key', () => {
|
test('should error on computed key', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
compile(
|
compile(
|
||||||
`<script setup>const { [foo]: bar } = defineProps(['foo'])</script>`
|
`<script setup>const { [foo]: bar } = defineProps(['foo'])</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`destructure cannot use computed key`)
|
).toThrow(`destructure cannot use computed key`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -363,8 +363,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
compile(
|
compile(
|
||||||
`<script setup lang="ts">
|
`<script setup lang="ts">
|
||||||
const { foo } = withDefaults(defineProps<{ foo: string }>(), { foo: 'foo' })
|
const { foo } = withDefaults(defineProps<{ foo: string }>(), { foo: 'foo' })
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`withDefaults() is unnecessary when using destructure`)
|
).toThrow(`withDefaults() is unnecessary when using destructure`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -376,8 +376,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
const {
|
const {
|
||||||
foo = () => x
|
foo = () => x
|
||||||
} = defineProps(['foo'])
|
} = defineProps(['foo'])
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`cannot reference locally declared variables`)
|
).toThrow(`cannot reference locally declared variables`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -387,8 +387,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
`<script setup>
|
`<script setup>
|
||||||
const { foo } = defineProps(['foo'])
|
const { foo } = defineProps(['foo'])
|
||||||
foo = 'bar'
|
foo = 'bar'
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`Cannot assign to destructured props`)
|
).toThrow(`Cannot assign to destructured props`)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -396,8 +396,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
`<script setup>
|
`<script setup>
|
||||||
let { foo } = defineProps(['foo'])
|
let { foo } = defineProps(['foo'])
|
||||||
foo = 'bar'
|
foo = 'bar'
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`Cannot assign to destructured props`)
|
).toThrow(`Cannot assign to destructured props`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -408,10 +408,10 @@ describe('sfc reactive props destructure', () => {
|
||||||
import { watch } from 'vue'
|
import { watch } from 'vue'
|
||||||
const { foo } = defineProps(['foo'])
|
const { foo } = defineProps(['foo'])
|
||||||
watch(foo, () => {})
|
watch(foo, () => {})
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(
|
).toThrow(
|
||||||
`"foo" is a destructured prop and should not be passed directly to watch().`
|
`"foo" is a destructured prop and should not be passed directly to watch().`,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -420,10 +420,10 @@ describe('sfc reactive props destructure', () => {
|
||||||
import { watch as w } from 'vue'
|
import { watch as w } from 'vue'
|
||||||
const { foo } = defineProps(['foo'])
|
const { foo } = defineProps(['foo'])
|
||||||
w(foo, () => {})
|
w(foo, () => {})
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(
|
).toThrow(
|
||||||
`"foo" is a destructured prop and should not be passed directly to watch().`
|
`"foo" is a destructured prop and should not be passed directly to watch().`,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -432,10 +432,10 @@ describe('sfc reactive props destructure', () => {
|
||||||
import { toRef } from 'vue'
|
import { toRef } from 'vue'
|
||||||
const { foo } = defineProps(['foo'])
|
const { foo } = defineProps(['foo'])
|
||||||
toRef(foo)
|
toRef(foo)
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(
|
).toThrow(
|
||||||
`"foo" is a destructured prop and should not be passed directly to toRef().`
|
`"foo" is a destructured prop and should not be passed directly to toRef().`,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(() =>
|
expect(() =>
|
||||||
|
@ -444,10 +444,10 @@ describe('sfc reactive props destructure', () => {
|
||||||
import { toRef as r } from 'vue'
|
import { toRef as r } from 'vue'
|
||||||
const { foo } = defineProps(['foo'])
|
const { foo } = defineProps(['foo'])
|
||||||
r(foo)
|
r(foo)
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(
|
).toThrow(
|
||||||
`"foo" is a destructured prop and should not be passed directly to toRef().`
|
`"foo" is a destructured prop and should not be passed directly to toRef().`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -457,8 +457,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
compile(
|
compile(
|
||||||
`<script setup lang="ts">
|
`<script setup lang="ts">
|
||||||
const { foo = 'hello' } = defineProps<{ foo?: number }>()
|
const { foo = 'hello' } = defineProps<{ foo?: number }>()
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).toThrow(`Default value of prop "foo" does not match declared type.`)
|
).toThrow(`Default value of prop "foo" does not match declared type.`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -472,8 +472,8 @@ describe('sfc reactive props destructure', () => {
|
||||||
const { error: e, info } = useRequest();
|
const { error: e, info } = useRequest();
|
||||||
watch(e, () => {});
|
watch(e, () => {});
|
||||||
watch(info, () => {});
|
watch(info, () => {});
|
||||||
</script>`
|
</script>`,
|
||||||
)
|
),
|
||||||
).not.toThrowError()
|
).not.toThrowError()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||||
|
|
||||||
describe('defineSlots()', () => {
|
describe('defineSlots()', () => {
|
||||||
test('basic usage', () => {
|
test('basic usage', () => {
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { BindingTypes } from '@vue/compiler-core'
|
import { BindingTypes } from '@vue/compiler-core'
|
||||||
import { SFCScriptCompileOptions } from '../../src'
|
import type { SFCScriptCompileOptions } from '../../src'
|
||||||
import { compileSFCScript, assertCode } from '../utils'
|
import { assertCode, compileSFCScript } from '../utils'
|
||||||
|
|
||||||
describe('sfc hoist static', () => {
|
describe('sfc hoist static', () => {
|
||||||
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
||||||
return compileSFCScript(src, {
|
return compileSFCScript(src, {
|
||||||
inlineTemplate: true,
|
inlineTemplate: true,
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ describe('sfc hoist static', () => {
|
||||||
boolean: BindingTypes.LITERAL_CONST,
|
boolean: BindingTypes.LITERAL_CONST,
|
||||||
nil: BindingTypes.LITERAL_CONST,
|
nil: BindingTypes.LITERAL_CONST,
|
||||||
bigint: BindingTypes.LITERAL_CONST,
|
bigint: BindingTypes.LITERAL_CONST,
|
||||||
template: BindingTypes.LITERAL_CONST
|
template: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -57,7 +57,7 @@ describe('sfc hoist static', () => {
|
||||||
binary: BindingTypes.LITERAL_CONST,
|
binary: BindingTypes.LITERAL_CONST,
|
||||||
conditional: BindingTypes.LITERAL_CONST,
|
conditional: BindingTypes.LITERAL_CONST,
|
||||||
unary: BindingTypes.LITERAL_CONST,
|
unary: BindingTypes.LITERAL_CONST,
|
||||||
sequence: BindingTypes.LITERAL_CONST
|
sequence: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -79,7 +79,7 @@ describe('sfc hoist static', () => {
|
||||||
expect(content.startsWith(hoistCode)).toBe(true)
|
expect(content.startsWith(hoistCode)).toBe(true)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.PROPS,
|
foo: BindingTypes.PROPS,
|
||||||
defaultValue: BindingTypes.LITERAL_CONST
|
defaultValue: BindingTypes.LITERAL_CONST,
|
||||||
})
|
})
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -100,7 +100,7 @@ describe('sfc hoist static', () => {
|
||||||
KEY1: BindingTypes.SETUP_LET,
|
KEY1: BindingTypes.SETUP_LET,
|
||||||
KEY2: BindingTypes.SETUP_LET,
|
KEY2: BindingTypes.SETUP_LET,
|
||||||
regex: BindingTypes.SETUP_CONST,
|
regex: BindingTypes.SETUP_CONST,
|
||||||
undef: BindingTypes.SETUP_MAYBE_REF
|
undef: BindingTypes.SETUP_MAYBE_REF,
|
||||||
})
|
})
|
||||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
|
@ -131,7 +131,7 @@ describe('sfc hoist static', () => {
|
||||||
KEY4: BindingTypes.SETUP_CONST,
|
KEY4: BindingTypes.SETUP_CONST,
|
||||||
KEY5: BindingTypes.SETUP_CONST,
|
KEY5: BindingTypes.SETUP_CONST,
|
||||||
KEY6: BindingTypes.SETUP_CONST,
|
KEY6: BindingTypes.SETUP_CONST,
|
||||||
i: BindingTypes.SETUP_LET
|
i: BindingTypes.SETUP_LET,
|
||||||
})
|
})
|
||||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
|
@ -149,7 +149,7 @@ describe('sfc hoist static', () => {
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
arr: BindingTypes.SETUP_CONST,
|
arr: BindingTypes.SETUP_CONST,
|
||||||
obj: BindingTypes.SETUP_CONST
|
obj: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
|
@ -169,7 +169,7 @@ describe('sfc hoist static', () => {
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
Foo: BindingTypes.SETUP_CONST,
|
Foo: BindingTypes.SETUP_CONST,
|
||||||
fn: BindingTypes.SETUP_CONST,
|
fn: BindingTypes.SETUP_CONST,
|
||||||
fn2: BindingTypes.SETUP_CONST
|
fn2: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
|
@ -185,7 +185,7 @@ describe('sfc hoist static', () => {
|
||||||
</script>
|
</script>
|
||||||
`)
|
`)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.SETUP_CONST
|
foo: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -197,10 +197,10 @@ describe('sfc hoist static', () => {
|
||||||
const foo = 'bar'
|
const foo = 'bar'
|
||||||
</script>
|
</script>
|
||||||
`,
|
`,
|
||||||
{ hoistStatic: false }
|
{ hoistStatic: false },
|
||||||
)
|
)
|
||||||
expect(bindings).toStrictEqual({
|
expect(bindings).toStrictEqual({
|
||||||
foo: BindingTypes.SETUP_CONST
|
foo: BindingTypes.SETUP_CONST,
|
||||||
})
|
})
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -212,7 +212,7 @@ describe('sfc hoist static', () => {
|
||||||
const foo = 'bar'
|
const foo = 'bar'
|
||||||
</script>
|
</script>
|
||||||
<template>{{ foo }}</template>
|
<template>{{ foo }}</template>
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch('_toDisplayString(foo)')
|
expect(content).toMatch('_toDisplayString(foo)')
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { normalize } from 'node:path'
|
import { normalize } from 'node:path'
|
||||||
import { Identifier } from '@babel/types'
|
import type { Identifier } from '@babel/types'
|
||||||
import { SFCScriptCompileOptions, parse } from '../../src'
|
import { type SFCScriptCompileOptions, parse } from '../../src'
|
||||||
import { ScriptCompileContext } from '../../src/script/context'
|
import { ScriptCompileContext } from '../../src/script/context'
|
||||||
import {
|
import {
|
||||||
inferRuntimeType,
|
inferRuntimeType,
|
||||||
invalidateTypeCache,
|
invalidateTypeCache,
|
||||||
recordImports,
|
recordImports,
|
||||||
|
registerTS,
|
||||||
resolveTypeElements,
|
resolveTypeElements,
|
||||||
registerTS
|
|
||||||
} from '../../src/script/resolveType'
|
} from '../../src/script/resolveType'
|
||||||
|
|
||||||
import ts from 'typescript'
|
import ts from 'typescript'
|
||||||
|
@ -25,7 +25,7 @@ describe('resolveType', () => {
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
bar: ['Function'],
|
bar: ['Function'],
|
||||||
baz: ['String']
|
baz: ['String'],
|
||||||
})
|
})
|
||||||
expect(calls?.length).toBe(2)
|
expect(calls?.length).toBe(2)
|
||||||
})
|
})
|
||||||
|
@ -35,9 +35,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
type Aliased = { foo: number }
|
type Aliased = { foo: number }
|
||||||
defineProps<Aliased>()
|
defineProps<Aliased>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number']
|
foo: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -46,9 +46,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
export type Aliased = { foo: number }
|
export type Aliased = { foo: number }
|
||||||
defineProps<Aliased>()
|
defineProps<Aliased>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number']
|
foo: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -57,9 +57,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
interface Aliased { foo: number }
|
interface Aliased { foo: number }
|
||||||
defineProps<Aliased>()
|
defineProps<Aliased>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number']
|
foo: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -68,9 +68,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
export interface Aliased { foo: number }
|
export interface Aliased { foo: number }
|
||||||
defineProps<Aliased>()
|
defineProps<Aliased>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number']
|
foo: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -82,12 +82,12 @@ describe('resolveType', () => {
|
||||||
interface C { c: string }
|
interface C { c: string }
|
||||||
interface Aliased extends B, C { foo: number }
|
interface Aliased extends B, C { foo: number }
|
||||||
defineProps<Aliased>()
|
defineProps<Aliased>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
a: ['Function'],
|
a: ['Function'],
|
||||||
b: ['Boolean'],
|
b: ['Boolean'],
|
||||||
c: ['String'],
|
c: ['String'],
|
||||||
foo: ['Number']
|
foo: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -96,9 +96,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
class Foo {}
|
class Foo {}
|
||||||
defineProps<{ foo: Foo }>()
|
defineProps<{ foo: Foo }>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Object']
|
foo: ['Object'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ describe('resolveType', () => {
|
||||||
expect(
|
expect(
|
||||||
resolve(`
|
resolve(`
|
||||||
defineProps<(e: 'foo') => void>()
|
defineProps<(e: 'foo') => void>()
|
||||||
`).calls?.length
|
`).calls?.length,
|
||||||
).toBe(1)
|
).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
type Fn = (e: 'foo') => void
|
type Fn = (e: 'foo') => void
|
||||||
defineProps<Fn>()
|
defineProps<Fn>()
|
||||||
`).calls?.length
|
`).calls?.length,
|
||||||
).toBe(1)
|
).toBe(1)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -126,13 +126,13 @@ describe('resolveType', () => {
|
||||||
type Bar = { bar: string }
|
type Bar = { bar: string }
|
||||||
type Baz = { bar: string | boolean }
|
type Baz = { bar: string | boolean }
|
||||||
defineProps<{ self: any } & Foo & Bar & Baz>()
|
defineProps<{ self: any } & Foo & Bar & Baz>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
self: ['Unknown'],
|
self: ['Unknown'],
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
// both Bar & Baz has 'bar', but Baz['bar] is wider so it should be
|
// both Bar & Baz has 'bar', but Baz['bar] is wider so it should be
|
||||||
// preferred
|
// preferred
|
||||||
bar: ['String', 'Boolean']
|
bar: ['String', 'Boolean'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -156,12 +156,12 @@ describe('resolveType', () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
defineProps<CommonProps & ConditionalProps>()
|
defineProps<CommonProps & ConditionalProps>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
size: ['String'],
|
size: ['String'],
|
||||||
color: ['String', 'Number'],
|
color: ['String', 'Number'],
|
||||||
appearance: ['String'],
|
appearance: ['String'],
|
||||||
note: ['String']
|
note: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -173,12 +173,12 @@ describe('resolveType', () => {
|
||||||
defineProps<{
|
defineProps<{
|
||||||
[\`_\${T}_\${S}_\`]: string
|
[\`_\${T}_\${S}_\`]: string
|
||||||
}>()
|
}>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
_foo_x_: ['String'],
|
_foo_x_: ['String'],
|
||||||
_foo_y_: ['String'],
|
_foo_y_: ['String'],
|
||||||
_bar_x_: ['String'],
|
_bar_x_: ['String'],
|
||||||
_bar_y_: ['String']
|
_bar_y_: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ describe('resolveType', () => {
|
||||||
} & {
|
} & {
|
||||||
[K in \`x\${T}\`]: string
|
[K in \`x\${T}\`]: string
|
||||||
}>()
|
}>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String', 'Number'],
|
foo: ['String', 'Number'],
|
||||||
bar: ['String', 'Number'],
|
bar: ['String', 'Number'],
|
||||||
|
@ -204,7 +204,7 @@ describe('resolveType', () => {
|
||||||
FOO: ['String'],
|
FOO: ['String'],
|
||||||
xfoo: ['String'],
|
xfoo: ['String'],
|
||||||
xbar: ['String'],
|
xbar: ['String'],
|
||||||
optional: ['Boolean']
|
optional: ['Boolean'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -213,14 +213,14 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
type T = { foo: number, bar: string }
|
type T = { foo: number, bar: string }
|
||||||
defineProps<Partial<T>>()
|
defineProps<Partial<T>>()
|
||||||
`).raw.props
|
`).raw.props,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
foo: {
|
foo: {
|
||||||
optional: true
|
optional: true,
|
||||||
},
|
},
|
||||||
bar: {
|
bar: {
|
||||||
optional: true
|
optional: true,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -229,14 +229,14 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
type T = { foo?: number, bar?: string }
|
type T = { foo?: number, bar?: string }
|
||||||
defineProps<Required<T>>()
|
defineProps<Required<T>>()
|
||||||
`).raw.props
|
`).raw.props,
|
||||||
).toMatchObject({
|
).toMatchObject({
|
||||||
foo: {
|
foo: {
|
||||||
optional: false
|
optional: false,
|
||||||
},
|
},
|
||||||
bar: {
|
bar: {
|
||||||
optional: false
|
optional: false,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -246,10 +246,10 @@ describe('resolveType', () => {
|
||||||
type T = { foo: number, bar: string, baz: boolean }
|
type T = { foo: number, bar: string, baz: boolean }
|
||||||
type K = 'foo' | 'bar'
|
type K = 'foo' | 'bar'
|
||||||
defineProps<Pick<T, K>>()
|
defineProps<Pick<T, K>>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -259,9 +259,9 @@ describe('resolveType', () => {
|
||||||
type T = { foo: number, bar: string, baz: boolean }
|
type T = { foo: number, bar: string, baz: boolean }
|
||||||
type K = 'foo' | 'bar'
|
type K = 'foo' | 'bar'
|
||||||
defineProps<Omit<T, K>>()
|
defineProps<Omit<T, K>>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
baz: ['Boolean']
|
baz: ['Boolean'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -271,9 +271,9 @@ describe('resolveType', () => {
|
||||||
type T = { bar: number }
|
type T = { bar: number }
|
||||||
type S = { nested: { foo: T['bar'] }}
|
type S = { nested: { foo: T['bar'] }}
|
||||||
defineProps<S['nested']>()
|
defineProps<S['nested']>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number']
|
foo: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -284,10 +284,10 @@ describe('resolveType', () => {
|
||||||
type T = { foo: string, bar: number }
|
type T = { foo: string, bar: number }
|
||||||
type S = { foo: { foo: T[string] }, bar: { bar: string } }
|
type S = { foo: { foo: T[string] }, bar: { bar: string } }
|
||||||
defineProps<S[K]>()
|
defineProps<S[K]>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String', 'Number'],
|
foo: ['String', 'Number'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -299,12 +299,12 @@ describe('resolveType', () => {
|
||||||
type T = [1, 'foo']
|
type T = [1, 'foo']
|
||||||
type TT = [foo: 1, bar: 'foo']
|
type TT = [foo: 1, bar: 'foo']
|
||||||
defineProps<{ foo: A[number], bar: AA[number], tuple: T[number], namedTuple: TT[number] }>()
|
defineProps<{ foo: A[number], bar: AA[number], tuple: T[number], namedTuple: TT[number] }>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String', 'Number'],
|
foo: ['String', 'Number'],
|
||||||
bar: ['String'],
|
bar: ['String'],
|
||||||
tuple: ['Number', 'String'],
|
tuple: ['Number', 'String'],
|
||||||
namedTuple: ['Number', 'String']
|
namedTuple: ['Number', 'String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -321,9 +321,9 @@ describe('resolveType', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defineProps<Foo.Bar.A>()
|
defineProps<Foo.Bar.A>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number']
|
foo: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -340,10 +340,10 @@ describe('resolveType', () => {
|
||||||
foo: Foo['a'],
|
foo: Foo['a'],
|
||||||
bar: Foo['b']
|
bar: Foo['b']
|
||||||
}>()
|
}>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Number']
|
bar: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -360,10 +360,10 @@ describe('resolveType', () => {
|
||||||
foo: Foo.A,
|
foo: Foo.A,
|
||||||
bar: Foo.B
|
bar: Foo.B
|
||||||
}>()
|
}>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Number']
|
bar: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -380,10 +380,10 @@ describe('resolveType', () => {
|
||||||
foo: Foo.A,
|
foo: Foo.A,
|
||||||
bar: Foo['b']
|
bar: Foo['b']
|
||||||
}>()
|
}>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Number']
|
bar: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -399,9 +399,9 @@ describe('resolveType', () => {
|
||||||
defineProps<{
|
defineProps<{
|
||||||
foo: Foo
|
foo: Foo
|
||||||
}>()
|
}>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['Number', 'String']
|
foo: ['Number', 'String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -410,9 +410,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
declare const a: string
|
declare const a: string
|
||||||
defineProps<{ foo: typeof a }>()
|
defineProps<{ foo: typeof a }>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -429,11 +429,11 @@ describe('resolveType', () => {
|
||||||
}
|
}
|
||||||
type Props = ExtractPropTypes<typeof props>
|
type Props = ExtractPropTypes<typeof props>
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Boolean']
|
bar: ['Boolean'],
|
||||||
})
|
})
|
||||||
expect(raw.props.bar.optional).toBe(false)
|
expect(raw.props.bar.optional).toBe(false)
|
||||||
})
|
})
|
||||||
|
@ -447,11 +447,11 @@ describe('resolveType', () => {
|
||||||
}
|
}
|
||||||
type Props = Partial<import('vue').ExtractPropTypes<ReturnType<typeof props>>>
|
type Props = Partial<import('vue').ExtractPropTypes<ReturnType<typeof props>>>
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
`
|
`,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Boolean']
|
bar: ['Boolean'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -461,9 +461,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
type Props<T> = T
|
type Props<T> = T
|
||||||
defineProps<Props<{ foo: string }>>()
|
defineProps<Props<{ foo: string }>>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -474,11 +474,11 @@ describe('resolveType', () => {
|
||||||
type Bar = { bar: number; }
|
type Bar = { bar: number; }
|
||||||
type Props<T,U> = T & U & { baz: boolean }
|
type Props<T,U> = T & U & { baz: boolean }
|
||||||
defineProps<Props<Foo, Bar>>()
|
defineProps<Props<Foo, Bar>>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Number'],
|
bar: ['Number'],
|
||||||
baz: ['Boolean']
|
baz: ['Boolean'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -489,9 +489,9 @@ describe('resolveType', () => {
|
||||||
type Props<T> = Aliased<T>
|
type Props<T> = Aliased<T>
|
||||||
type Foo = { foo: string; }
|
type Foo = { foo: string; }
|
||||||
defineProps<Props<Foo>>()
|
defineProps<Props<Foo>>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -500,9 +500,9 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
type Aliased<T> = { foo: T }
|
type Aliased<T> = { foo: T }
|
||||||
defineProps<Aliased<string>>()
|
defineProps<Aliased<string>>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -514,25 +514,25 @@ describe('resolveType', () => {
|
||||||
}
|
}
|
||||||
type Foo = string
|
type Foo = string
|
||||||
defineProps<Props<Foo>>()
|
defineProps<Props<Foo>>()
|
||||||
`).props
|
`).props,
|
||||||
).toStrictEqual({
|
).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
test('generic from external-file', () => {
|
test('generic from external-file', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': 'export type P<T> = { foo: T }'
|
'/foo.ts': 'export type P<T> = { foo: T }',
|
||||||
}
|
}
|
||||||
const { props } = resolve(
|
const { props } = resolve(
|
||||||
`
|
`
|
||||||
import { P } from './foo'
|
import { P } from './foo'
|
||||||
defineProps<P<string>>()
|
defineProps<P<string>>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -544,7 +544,7 @@ describe('resolveType', () => {
|
||||||
'/bar.d.ts':
|
'/bar.d.ts':
|
||||||
'type X = { bar: string }; export { X as Y };' +
|
'type X = { bar: string }; export { X as Y };' +
|
||||||
// verify that we can parse syntax that is only valid in d.ts
|
// verify that we can parse syntax that is only valid in d.ts
|
||||||
'export const baz: boolean'
|
'export const baz: boolean',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
|
@ -552,11 +552,11 @@ describe('resolveType', () => {
|
||||||
import { Y as PP } from './bar'
|
import { Y as PP } from './bar'
|
||||||
defineProps<P & PP>()
|
defineProps<P & PP>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -568,7 +568,7 @@ describe('resolveType', () => {
|
||||||
'type X = { bar: string }; export { X as Y };' +
|
'type X = { bar: string }; export { X as Y };' +
|
||||||
// verify that we can parse syntax that is only valid in d.ts
|
// verify that we can parse syntax that is only valid in d.ts
|
||||||
'export const baz: boolean',
|
'export const baz: boolean',
|
||||||
'C:\\Test\\FolderB\\buz.ts': 'export type Z = { buz: string }'
|
'C:\\Test\\FolderB\\buz.ts': 'export type Z = { buz: string }',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
|
@ -579,32 +579,32 @@ describe('resolveType', () => {
|
||||||
`,
|
`,
|
||||||
files,
|
files,
|
||||||
{},
|
{},
|
||||||
'C:\\Test\\FolderA\\Test.vue'
|
'C:\\Test\\FolderA\\Test.vue',
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
bar: ['String'],
|
bar: ['String'],
|
||||||
buz: ['String']
|
buz: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps].map(normalize)).toStrictEqual(
|
expect(deps && [...deps].map(normalize)).toStrictEqual(
|
||||||
Object.keys(files).map(normalize)
|
Object.keys(files).map(normalize),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
// #8244
|
// #8244
|
||||||
test('utility type in external file', () => {
|
test('utility type in external file', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': 'type A = { n?: number }; export type B = Required<A>'
|
'/foo.ts': 'type A = { n?: number }; export type B = Required<A>',
|
||||||
}
|
}
|
||||||
const { props } = resolve(
|
const { props } = resolve(
|
||||||
`
|
`
|
||||||
import { B } from './foo'
|
import { B } from './foo'
|
||||||
defineProps<B>()
|
defineProps<B>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
n: ['Number']
|
n: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -613,7 +613,7 @@ describe('resolveType', () => {
|
||||||
'/foo.vue':
|
'/foo.vue':
|
||||||
'<script lang="ts">export type P = { foo: number }</script>',
|
'<script lang="ts">export type P = { foo: number }</script>',
|
||||||
'/bar.vue':
|
'/bar.vue':
|
||||||
'<script setup lang="tsx">export type P = { bar: string }</script>'
|
'<script setup lang="tsx">export type P = { bar: string }</script>',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
|
@ -621,11 +621,11 @@ describe('resolveType', () => {
|
||||||
import { P as PP } from './bar.vue'
|
import { P as PP } from './bar.vue'
|
||||||
defineProps<P & PP>()
|
defineProps<P & PP>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -635,18 +635,18 @@ describe('resolveType', () => {
|
||||||
'/foo.ts': `import type { P as PP } from './nested/bar.vue'
|
'/foo.ts': `import type { P as PP } from './nested/bar.vue'
|
||||||
export type P = { foo: number } & PP`,
|
export type P = { foo: number } & PP`,
|
||||||
'/nested/bar.vue':
|
'/nested/bar.vue':
|
||||||
'<script setup lang="ts">export type P = { bar: string }</script>'
|
'<script setup lang="ts">export type P = { bar: string }</script>',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
import { P } from './foo'
|
import { P } from './foo'
|
||||||
defineProps<P>()
|
defineProps<P>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -654,17 +654,17 @@ describe('resolveType', () => {
|
||||||
test('relative (chained, re-export)', () => {
|
test('relative (chained, re-export)', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': `export { P as PP } from './bar'`,
|
'/foo.ts': `export { P as PP } from './bar'`,
|
||||||
'/bar.ts': 'export type P = { bar: string }'
|
'/bar.ts': 'export type P = { bar: string }',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
import { PP as P } from './foo'
|
import { PP as P } from './foo'
|
||||||
defineProps<P>()
|
defineProps<P>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -672,17 +672,17 @@ describe('resolveType', () => {
|
||||||
test('relative (chained, export *)', () => {
|
test('relative (chained, export *)', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': `export * from './bar'`,
|
'/foo.ts': `export * from './bar'`,
|
||||||
'/bar.ts': 'export type P = { bar: string }'
|
'/bar.ts': 'export type P = { bar: string }',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
import { P } from './foo'
|
import { P } from './foo'
|
||||||
defineProps<P>()
|
defineProps<P>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -690,7 +690,7 @@ describe('resolveType', () => {
|
||||||
test('relative (default export)', () => {
|
test('relative (default export)', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': `export default interface P { foo: string }`,
|
'/foo.ts': `export default interface P { foo: string }`,
|
||||||
'/bar.ts': `type X = { bar: string }; export default X`
|
'/bar.ts': `type X = { bar: string }; export default X`,
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
|
@ -698,11 +698,11 @@ describe('resolveType', () => {
|
||||||
import X from './bar'
|
import X from './bar'
|
||||||
defineProps<P & X>()
|
defineProps<P & X>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -711,7 +711,7 @@ describe('resolveType', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/bar.ts': `export { default } from './foo'`,
|
'/bar.ts': `export { default } from './foo'`,
|
||||||
'/foo.ts': `export default interface P { foo: string }; export interface PP { bar: number }`,
|
'/foo.ts': `export default interface P { foo: string }; export interface PP { bar: number }`,
|
||||||
'/baz.ts': `export { PP as default } from './foo'`
|
'/baz.ts': `export { PP as default } from './foo'`,
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
|
@ -719,11 +719,11 @@ describe('resolveType', () => {
|
||||||
import PP from './baz'
|
import PP from './baz'
|
||||||
defineProps<P & PP>()
|
defineProps<P & PP>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Number']
|
bar: ['Number'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -732,17 +732,17 @@ describe('resolveType', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': `export default interface P { foo: string }`,
|
'/foo.ts': `export default interface P { foo: string }`,
|
||||||
'/bar.ts': `export default interface PP { bar: number }`,
|
'/bar.ts': `export default interface PP { bar: number }`,
|
||||||
'/baz.ts': `export { default as X } from './foo'; export { default as XX } from './bar'; `
|
'/baz.ts': `export { default as X } from './foo'; export { default as XX } from './bar'; `,
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`import { X, XX } from './baz'
|
`import { X, XX } from './baz'
|
||||||
defineProps<X & XX>()
|
defineProps<X & XX>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Number']
|
bar: ['Number'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(['/baz.ts', '/foo.ts', '/bar.ts'])
|
expect(deps && [...deps]).toStrictEqual(['/baz.ts', '/foo.ts', '/bar.ts'])
|
||||||
})
|
})
|
||||||
|
@ -750,17 +750,17 @@ describe('resolveType', () => {
|
||||||
test('relative (dynamic import)', () => {
|
test('relative (dynamic import)', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': `export type P = { foo: string, bar: import('./bar').N }`,
|
'/foo.ts': `export type P = { foo: string, bar: import('./bar').N }`,
|
||||||
'/bar.ts': 'export type N = number'
|
'/bar.ts': 'export type N = number',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
defineProps<import('./foo').P>()
|
defineProps<import('./foo').P>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String'],
|
foo: ['String'],
|
||||||
bar: ['Number']
|
bar: ['Number'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -770,17 +770,17 @@ describe('resolveType', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.d.ts':
|
'/foo.d.ts':
|
||||||
'import { PP } from "./bar.js"; export type P = { foo: PP }',
|
'import { PP } from "./bar.js"; export type P = { foo: PP }',
|
||||||
'/bar.d.ts': 'export type PP = "foo" | "bar"'
|
'/bar.d.ts': 'export type PP = "foo" | "bar"',
|
||||||
}
|
}
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
`
|
`
|
||||||
import { P } from './foo'
|
import { P } from './foo'
|
||||||
defineProps<P>()
|
defineProps<P>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -788,17 +788,17 @@ describe('resolveType', () => {
|
||||||
test('ts module resolve', () => {
|
test('ts module resolve', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/node_modules/foo/package.json': JSON.stringify({
|
'/node_modules/foo/package.json': JSON.stringify({
|
||||||
types: 'index.d.ts'
|
types: 'index.d.ts',
|
||||||
}),
|
}),
|
||||||
'/node_modules/foo/index.d.ts': 'export type P = { foo: number }',
|
'/node_modules/foo/index.d.ts': 'export type P = { foo: number }',
|
||||||
'/tsconfig.json': JSON.stringify({
|
'/tsconfig.json': JSON.stringify({
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
paths: {
|
paths: {
|
||||||
bar: ['./pp.ts']
|
bar: ['./pp.ts'],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
'/pp.ts': 'export type PP = { bar: string }'
|
'/pp.ts': 'export type PP = { bar: string }',
|
||||||
}
|
}
|
||||||
|
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
|
@ -807,16 +807,16 @@ describe('resolveType', () => {
|
||||||
import { PP } from 'bar'
|
import { PP } from 'bar'
|
||||||
defineProps<P & PP>()
|
defineProps<P & PP>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
foo: ['Number'],
|
foo: ['Number'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual([
|
expect(deps && [...deps]).toStrictEqual([
|
||||||
'/node_modules/foo/index.d.ts',
|
'/node_modules/foo/index.d.ts',
|
||||||
'/pp.ts'
|
'/pp.ts',
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -825,23 +825,23 @@ describe('resolveType', () => {
|
||||||
'/tsconfig.json': JSON.stringify({
|
'/tsconfig.json': JSON.stringify({
|
||||||
references: [
|
references: [
|
||||||
{
|
{
|
||||||
path: './tsconfig.app.json'
|
path: './tsconfig.app.json',
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}),
|
}),
|
||||||
'/tsconfig.app.json': JSON.stringify({
|
'/tsconfig.app.json': JSON.stringify({
|
||||||
include: ['**/*.ts', '**/*.vue'],
|
include: ['**/*.ts', '**/*.vue'],
|
||||||
extends: './tsconfig.web.json'
|
extends: './tsconfig.web.json',
|
||||||
}),
|
}),
|
||||||
'/tsconfig.web.json': JSON.stringify({
|
'/tsconfig.web.json': JSON.stringify({
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
composite: true,
|
composite: true,
|
||||||
paths: {
|
paths: {
|
||||||
bar: ['./user.ts']
|
bar: ['./user.ts'],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
'/user.ts': 'export type User = { bar: string }'
|
'/user.ts': 'export type User = { bar: string }',
|
||||||
}
|
}
|
||||||
|
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
|
@ -849,11 +849,11 @@ describe('resolveType', () => {
|
||||||
import { User } from 'bar'
|
import { User } from 'bar'
|
||||||
defineProps<User>()
|
defineProps<User>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(['/user.ts'])
|
expect(deps && [...deps]).toStrictEqual(['/user.ts'])
|
||||||
})
|
})
|
||||||
|
@ -864,12 +864,12 @@ describe('resolveType', () => {
|
||||||
compilerOptions: {
|
compilerOptions: {
|
||||||
include: ['**/*.ts', '**/*.vue'],
|
include: ['**/*.ts', '**/*.vue'],
|
||||||
paths: {
|
paths: {
|
||||||
'@/*': ['./src/*']
|
'@/*': ['./src/*'],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
'/src/Foo.vue':
|
'/src/Foo.vue':
|
||||||
'<script lang="ts">export type P = { bar: string }</script>'
|
'<script lang="ts">export type P = { bar: string }</script>',
|
||||||
}
|
}
|
||||||
|
|
||||||
const { props, deps } = resolve(
|
const { props, deps } = resolve(
|
||||||
|
@ -877,11 +877,11 @@ describe('resolveType', () => {
|
||||||
import { P } from '@/Foo.vue'
|
import { P } from '@/Foo.vue'
|
||||||
defineProps<P>()
|
defineProps<P>()
|
||||||
`,
|
`,
|
||||||
files
|
files,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(['/src/Foo.vue'])
|
expect(deps && [...deps]).toStrictEqual(['/src/Foo.vue'])
|
||||||
})
|
})
|
||||||
|
@ -898,16 +898,16 @@ describe('resolveType', () => {
|
||||||
type PP = { bar: string }
|
type PP = { bar: string }
|
||||||
}
|
}
|
||||||
export {}
|
export {}
|
||||||
`
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
const { props, deps } = resolve(`defineProps<App.User & PP>()`, files, {
|
const { props, deps } = resolve(`defineProps<App.User & PP>()`, files, {
|
||||||
globalTypeFiles: Object.keys(files)
|
globalTypeFiles: Object.keys(files),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
name: ['String'],
|
name: ['String'],
|
||||||
bar: ['String']
|
bar: ['String'],
|
||||||
})
|
})
|
||||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||||
})
|
})
|
||||||
|
@ -927,33 +927,33 @@ describe('resolveType', () => {
|
||||||
id: string
|
id: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`
|
`,
|
||||||
}
|
}
|
||||||
|
|
||||||
const { props } = resolve(`defineProps<App.Data.AircraftData>()`, files, {
|
const { props } = resolve(`defineProps<App.Data.AircraftData>()`, files, {
|
||||||
globalTypeFiles: Object.keys(files)
|
globalTypeFiles: Object.keys(files),
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
id: ['String'],
|
id: ['String'],
|
||||||
manufacturer: ['Object']
|
manufacturer: ['Object'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
// #9871
|
// #9871
|
||||||
test('shared generics with different args', () => {
|
test('shared generics with different args', () => {
|
||||||
const files = {
|
const files = {
|
||||||
'/foo.ts': `export interface Foo<T> { value: T }`
|
'/foo.ts': `export interface Foo<T> { value: T }`,
|
||||||
}
|
}
|
||||||
const { props } = resolve(
|
const { props } = resolve(
|
||||||
`import type { Foo } from './foo'
|
`import type { Foo } from './foo'
|
||||||
defineProps<Foo<string>>()`,
|
defineProps<Foo<string>>()`,
|
||||||
files,
|
files,
|
||||||
undefined,
|
undefined,
|
||||||
`/One.vue`
|
`/One.vue`,
|
||||||
)
|
)
|
||||||
expect(props).toStrictEqual({
|
expect(props).toStrictEqual({
|
||||||
value: ['String']
|
value: ['String'],
|
||||||
})
|
})
|
||||||
const { props: props2 } = resolve(
|
const { props: props2 } = resolve(
|
||||||
`import type { Foo } from './foo'
|
`import type { Foo } from './foo'
|
||||||
|
@ -961,10 +961,10 @@ describe('resolveType', () => {
|
||||||
files,
|
files,
|
||||||
undefined,
|
undefined,
|
||||||
`/Two.vue`,
|
`/Two.vue`,
|
||||||
false /* do not invalidate cache */
|
false /* do not invalidate cache */,
|
||||||
)
|
)
|
||||||
expect(props2).toStrictEqual({
|
expect(props2).toStrictEqual({
|
||||||
value: ['Number']
|
value: ['Number'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -972,25 +972,25 @@ describe('resolveType', () => {
|
||||||
describe('errors', () => {
|
describe('errors', () => {
|
||||||
test('failed type reference', () => {
|
test('failed type reference', () => {
|
||||||
expect(() => resolve(`defineProps<X>()`)).toThrow(
|
expect(() => resolve(`defineProps<X>()`)).toThrow(
|
||||||
`Unresolvable type reference`
|
`Unresolvable type reference`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('unsupported computed keys', () => {
|
test('unsupported computed keys', () => {
|
||||||
expect(() => resolve(`defineProps<{ [Foo]: string }>()`)).toThrow(
|
expect(() => resolve(`defineProps<{ [Foo]: string }>()`)).toThrow(
|
||||||
`Unsupported computed key in type referenced by a macro`
|
`Unsupported computed key in type referenced by a macro`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('unsupported index type', () => {
|
test('unsupported index type', () => {
|
||||||
expect(() => resolve(`defineProps<X[K]>()`)).toThrow(
|
expect(() => resolve(`defineProps<X[K]>()`)).toThrow(
|
||||||
`Unsupported type when resolving index type`
|
`Unsupported type when resolving index type`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('failed import source resolve', () => {
|
test('failed import source resolve', () => {
|
||||||
expect(() =>
|
expect(() =>
|
||||||
resolve(`import { X } from './foo'; defineProps<X>()`)
|
resolve(`import { X } from './foo'; defineProps<X>()`),
|
||||||
).toThrow(`Failed to resolve import source "./foo"`)
|
).toThrow(`Failed to resolve import source "./foo"`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1001,7 +1001,7 @@ describe('resolveType', () => {
|
||||||
resolve(`
|
resolve(`
|
||||||
import type P from 'unknown'
|
import type P from 'unknown'
|
||||||
defineProps<{ foo: P }>()
|
defineProps<{ foo: P }>()
|
||||||
`)
|
`),
|
||||||
).not.toThrow()
|
).not.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1011,7 +1011,7 @@ describe('resolveType', () => {
|
||||||
import type Base from 'unknown'
|
import type Base from 'unknown'
|
||||||
interface Props extends Base {}
|
interface Props extends Base {}
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
`)
|
`),
|
||||||
).toThrow(`@vue-ignore`)
|
).toThrow(`@vue-ignore`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1026,11 +1026,11 @@ describe('resolveType', () => {
|
||||||
foo: string
|
foo: string
|
||||||
}
|
}
|
||||||
defineProps<Props>()
|
defineProps<Props>()
|
||||||
`))
|
`)),
|
||||||
).not.toThrow(`@vue-ignore`)
|
).not.toThrow(`@vue-ignore`)
|
||||||
|
|
||||||
expect(res.props).toStrictEqual({
|
expect(res.props).toStrictEqual({
|
||||||
foo: ['String']
|
foo: ['String'],
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1041,10 +1041,10 @@ function resolve(
|
||||||
files: Record<string, string> = {},
|
files: Record<string, string> = {},
|
||||||
options?: Partial<SFCScriptCompileOptions>,
|
options?: Partial<SFCScriptCompileOptions>,
|
||||||
sourceFileName: string = '/Test.vue',
|
sourceFileName: string = '/Test.vue',
|
||||||
invalidateCache = true
|
invalidateCache = true,
|
||||||
) {
|
) {
|
||||||
const { descriptor } = parse(`<script setup lang="ts">\n${code}\n</script>`, {
|
const { descriptor } = parse(`<script setup lang="ts">\n${code}\n</script>`, {
|
||||||
filename: sourceFileName
|
filename: sourceFileName,
|
||||||
})
|
})
|
||||||
const ctx = new ScriptCompileContext(descriptor, {
|
const ctx = new ScriptCompileContext(descriptor, {
|
||||||
id: 'test',
|
id: 'test',
|
||||||
|
@ -1054,9 +1054,9 @@ function resolve(
|
||||||
},
|
},
|
||||||
readFile(file) {
|
readFile(file) {
|
||||||
return files[file] ?? files[normalize(file)]
|
return files[file] ?? files[normalize(file)]
|
||||||
}
|
|
||||||
},
|
},
|
||||||
...options
|
},
|
||||||
|
...options,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (invalidateCache) {
|
if (invalidateCache) {
|
||||||
|
@ -1088,6 +1088,6 @@ function resolve(
|
||||||
props,
|
props,
|
||||||
calls: raw.calls,
|
calls: raw.calls,
|
||||||
deps: ctx.deps,
|
deps: ctx.deps,
|
||||||
raw
|
raw,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import {
|
import {
|
||||||
|
type SFCStyleCompileOptions,
|
||||||
compileStyle,
|
compileStyle,
|
||||||
compileStyleAsync,
|
compileStyleAsync,
|
||||||
SFCStyleCompileOptions
|
|
||||||
} from '../src/compileStyle'
|
} from '../src/compileStyle'
|
||||||
import path from 'path'
|
import path from 'node:path'
|
||||||
|
|
||||||
export function compileScoped(
|
export function compileScoped(
|
||||||
source: string,
|
source: string,
|
||||||
options?: Partial<SFCStyleCompileOptions>
|
options?: Partial<SFCStyleCompileOptions>,
|
||||||
): string {
|
): string {
|
||||||
const res = compileStyle({
|
const res = compileStyle({
|
||||||
source,
|
source,
|
||||||
filename: 'test.css',
|
filename: 'test.css',
|
||||||
id: 'data-v-test',
|
id: 'data-v-test',
|
||||||
scoped: true,
|
scoped: true,
|
||||||
...options
|
...options,
|
||||||
})
|
})
|
||||||
if (res.errors.length) {
|
if (res.errors.length) {
|
||||||
res.errors.forEach(err => {
|
res.errors.forEach(err => {
|
||||||
|
@ -28,34 +28,34 @@ export function compileScoped(
|
||||||
describe('SFC scoped CSS', () => {
|
describe('SFC scoped CSS', () => {
|
||||||
test('simple selectors', () => {
|
test('simple selectors', () => {
|
||||||
expect(compileScoped(`h1 { color: red; }`)).toMatch(
|
expect(compileScoped(`h1 { color: red; }`)).toMatch(
|
||||||
`h1[data-v-test] { color: red;`
|
`h1[data-v-test] { color: red;`,
|
||||||
)
|
)
|
||||||
expect(compileScoped(`.foo { color: red; }`)).toMatch(
|
expect(compileScoped(`.foo { color: red; }`)).toMatch(
|
||||||
`.foo[data-v-test] { color: red;`
|
`.foo[data-v-test] { color: red;`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('descendent selector', () => {
|
test('descendent selector', () => {
|
||||||
expect(compileScoped(`h1 .foo { color: red; }`)).toMatch(
|
expect(compileScoped(`h1 .foo { color: red; }`)).toMatch(
|
||||||
`h1 .foo[data-v-test] { color: red;`
|
`h1 .foo[data-v-test] { color: red;`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('multiple selectors', () => {
|
test('multiple selectors', () => {
|
||||||
expect(compileScoped(`h1 .foo, .bar, .baz { color: red; }`)).toMatch(
|
expect(compileScoped(`h1 .foo, .bar, .baz { color: red; }`)).toMatch(
|
||||||
`h1 .foo[data-v-test], .bar[data-v-test], .baz[data-v-test] { color: red;`
|
`h1 .foo[data-v-test], .bar[data-v-test], .baz[data-v-test] { color: red;`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('pseudo class', () => {
|
test('pseudo class', () => {
|
||||||
expect(compileScoped(`.foo:after { color: red; }`)).toMatch(
|
expect(compileScoped(`.foo:after { color: red; }`)).toMatch(
|
||||||
`.foo[data-v-test]:after { color: red;`
|
`.foo[data-v-test]:after { color: red;`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('pseudo element', () => {
|
test('pseudo element', () => {
|
||||||
expect(compileScoped(`::selection { display: none; }`)).toMatch(
|
expect(compileScoped(`::selection { display: none; }`)).toMatch(
|
||||||
'[data-v-test]::selection {'
|
'[data-v-test]::selection {',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -217,30 +217,30 @@ describe('SFC scoped CSS', () => {
|
||||||
to { opacity: 1; }
|
to { opacity: 1; }
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
{ id: 'data-v-test' }
|
{ id: 'data-v-test' },
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(style).toContain(
|
expect(style).toContain(
|
||||||
`.anim[data-v-test] {\n animation: color-test 5s infinite, other 5s;`
|
`.anim[data-v-test] {\n animation: color-test 5s infinite, other 5s;`,
|
||||||
)
|
)
|
||||||
expect(style).toContain(
|
expect(style).toContain(
|
||||||
`.anim-2[data-v-test] {\n animation-name: color-test`
|
`.anim-2[data-v-test] {\n animation-name: color-test`,
|
||||||
)
|
)
|
||||||
expect(style).toContain(
|
expect(style).toContain(
|
||||||
`.anim-3[data-v-test] {\n animation: 5s color-test infinite, 5s other;`
|
`.anim-3[data-v-test] {\n animation: 5s color-test infinite, 5s other;`,
|
||||||
)
|
)
|
||||||
expect(style).toContain(`@keyframes color-test {`)
|
expect(style).toContain(`@keyframes color-test {`)
|
||||||
expect(style).toContain(`@-webkit-keyframes color-test {`)
|
expect(style).toContain(`@-webkit-keyframes color-test {`)
|
||||||
|
|
||||||
expect(style).toContain(
|
expect(style).toContain(
|
||||||
`.anim-multiple[data-v-test] {\n animation: color-test 5s infinite,opacity-test 2s;`
|
`.anim-multiple[data-v-test] {\n animation: color-test 5s infinite,opacity-test 2s;`,
|
||||||
)
|
)
|
||||||
expect(style).toContain(
|
expect(style).toContain(
|
||||||
`.anim-multiple-2[data-v-test] {\n animation-name: color-test,opacity-test;`
|
`.anim-multiple-2[data-v-test] {\n animation-name: color-test,opacity-test;`,
|
||||||
)
|
)
|
||||||
expect(style).toContain(`@keyframes opacity-test {\nfrom { opacity: 0;`)
|
expect(style).toContain(`@keyframes opacity-test {\nfrom { opacity: 0;`)
|
||||||
expect(style).toContain(
|
expect(style).toContain(
|
||||||
`@-webkit-keyframes opacity-test {\nfrom { opacity: 0;`
|
`@-webkit-keyframes opacity-test {\nfrom { opacity: 0;`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -265,7 +265,7 @@ describe('SFC scoped CSS', () => {
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
expect(
|
expect(
|
||||||
`::v-deep usage as a combinator has been deprecated.`
|
`::v-deep usage as a combinator has been deprecated.`,
|
||||||
).toHaveBeenWarned()
|
).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -276,7 +276,7 @@ describe('SFC scoped CSS', () => {
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
expect(
|
expect(
|
||||||
`the >>> and /deep/ combinators have been deprecated.`
|
`the >>> and /deep/ combinators have been deprecated.`,
|
||||||
).toHaveBeenWarned()
|
).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -287,7 +287,7 @@ describe('SFC scoped CSS', () => {
|
||||||
}"
|
}"
|
||||||
`)
|
`)
|
||||||
expect(
|
expect(
|
||||||
`the >>> and /deep/ combinators have been deprecated.`
|
`the >>> and /deep/ combinators have been deprecated.`,
|
||||||
).toHaveBeenWarned()
|
).toHaveBeenWarned()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -299,7 +299,7 @@ describe('SFC CSS modules', () => {
|
||||||
source: `.red { color: red }\n.green { color: green }\n:global(.blue) { color: blue }`,
|
source: `.red { color: red }\n.green { color: green }\n:global(.blue) { color: blue }`,
|
||||||
filename: `test.css`,
|
filename: `test.css`,
|
||||||
id: 'test',
|
id: 'test',
|
||||||
modules: true
|
modules: true,
|
||||||
})
|
})
|
||||||
expect(result.modules).toBeDefined()
|
expect(result.modules).toBeDefined()
|
||||||
expect(result.modules!.red).toMatch('_red_')
|
expect(result.modules!.red).toMatch('_red_')
|
||||||
|
@ -316,8 +316,8 @@ describe('SFC CSS modules', () => {
|
||||||
modulesOptions: {
|
modulesOptions: {
|
||||||
scopeBehaviour: 'global',
|
scopeBehaviour: 'global',
|
||||||
generateScopedName: `[name]__[local]__[hash:base64:5]`,
|
generateScopedName: `[name]__[local]__[hash:base64:5]`,
|
||||||
localsConvention: 'camelCaseOnly'
|
localsConvention: 'camelCaseOnly',
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(result.modules).toBeDefined()
|
expect(result.modules).toBeDefined()
|
||||||
expect(result.modules!.fooBar).toMatch('__foo-bar__')
|
expect(result.modules!.fooBar).toMatch('__foo-bar__')
|
||||||
|
@ -333,11 +333,11 @@ describe('SFC style preprocessors', () => {
|
||||||
`,
|
`,
|
||||||
filename: path.resolve(__dirname, './fixture/test.scss'),
|
filename: path.resolve(__dirname, './fixture/test.scss'),
|
||||||
id: '',
|
id: '',
|
||||||
preprocessLang: 'scss'
|
preprocessLang: 'scss',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect([...res.dependencies]).toStrictEqual([
|
expect([...res.dependencies]).toStrictEqual([
|
||||||
path.join(__dirname, './fixture/import.scss')
|
path.join(__dirname, './fixture/import.scss'),
|
||||||
])
|
])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ describe('SFC style preprocessors', () => {
|
||||||
@mixin square($size) {
|
@mixin square($size) {
|
||||||
width: $size;
|
width: $size;
|
||||||
height: $size;
|
height: $size;
|
||||||
}`
|
}`,
|
||||||
},
|
},
|
||||||
source: `
|
source: `
|
||||||
.square {
|
.square {
|
||||||
|
@ -357,7 +357,7 @@ describe('SFC style preprocessors', () => {
|
||||||
`,
|
`,
|
||||||
filename: path.resolve(__dirname, './fixture/test.scss'),
|
filename: path.resolve(__dirname, './fixture/test.scss'),
|
||||||
id: '',
|
id: '',
|
||||||
preprocessLang: 'scss'
|
preprocessLang: 'scss',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(res.errors.length).toBe(0)
|
expect(res.errors.length).toBe(0)
|
||||||
|
@ -380,12 +380,12 @@ describe('SFC style preprocessors', () => {
|
||||||
width: $size;
|
width: $size;
|
||||||
height: $size;
|
height: $size;
|
||||||
}`
|
}`
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
source,
|
source,
|
||||||
filename,
|
filename,
|
||||||
id: '',
|
id: '',
|
||||||
preprocessLang: 'scss'
|
preprocessLang: 'scss',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(res.errors.length).toBe(0)
|
expect(res.errors.length).toBe(0)
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
import { RawSourceMap, SourceMapConsumer } from 'source-map-js'
|
import { type RawSourceMap, SourceMapConsumer } from 'source-map-js'
|
||||||
import {
|
import {
|
||||||
|
type SFCTemplateCompileOptions,
|
||||||
compileTemplate,
|
compileTemplate,
|
||||||
SFCTemplateCompileOptions
|
|
||||||
} from '../src/compileTemplate'
|
} from '../src/compileTemplate'
|
||||||
import { parse, SFCTemplateBlock } from '../src/parse'
|
import { type SFCTemplateBlock, parse } from '../src/parse'
|
||||||
import { compileScript } from '../src'
|
import { compileScript } from '../src'
|
||||||
|
|
||||||
function compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {
|
function compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {
|
||||||
return compileTemplate({
|
return compileTemplate({
|
||||||
...opts,
|
...opts,
|
||||||
id: ''
|
id: '',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +50,13 @@ body
|
||||||
p Cool Pug example!
|
p Cool Pug example!
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ filename: 'example.vue', sourceMap: true }
|
{ filename: 'example.vue', sourceMap: true },
|
||||||
).descriptor.template as SFCTemplateBlock
|
).descriptor.template as SFCTemplateBlock
|
||||||
|
|
||||||
const result = compile({
|
const result = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content,
|
source: template.content,
|
||||||
preprocessLang: template.lang
|
preprocessLang: template.lang,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.errors.length).toBe(0)
|
expect(result.errors.length).toBe(0)
|
||||||
|
@ -74,31 +74,31 @@ test('preprocess pug with indents and blank lines', () => {
|
||||||
p This is the last line.
|
p This is the last line.
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ filename: 'example.vue', sourceMap: true }
|
{ filename: 'example.vue', sourceMap: true },
|
||||||
).descriptor.template as SFCTemplateBlock
|
).descriptor.template as SFCTemplateBlock
|
||||||
|
|
||||||
const result = compile({
|
const result = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content,
|
source: template.content,
|
||||||
preprocessLang: template.lang
|
preprocessLang: template.lang,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.errors.length).toBe(0)
|
expect(result.errors.length).toBe(0)
|
||||||
expect(result.source).toBe(
|
expect(result.source).toBe(
|
||||||
'<body><h1>The next line contains four spaces.</h1><div class="container"><p>The next line is empty.</p></div><p>This is the last line.</p></body>'
|
'<body><h1>The next line contains four spaces.</h1><div class="container"><p>The next line is empty.</p></div><p>This is the last line.</p></body>',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('warn missing preprocessor', () => {
|
test('warn missing preprocessor', () => {
|
||||||
const template = parse(`<template lang="unknownLang">hi</template>\n`, {
|
const template = parse(`<template lang="unknownLang">hi</template>\n`, {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
sourceMap: true
|
sourceMap: true,
|
||||||
}).descriptor.template as SFCTemplateBlock
|
}).descriptor.template as SFCTemplateBlock
|
||||||
|
|
||||||
const result = compile({
|
const result = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content,
|
source: template.content,
|
||||||
preprocessLang: template.lang
|
preprocessLang: template.lang,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.errors.length).toBe(1)
|
expect(result.errors.length).toBe(1)
|
||||||
|
@ -110,8 +110,8 @@ test('transform asset url options', () => {
|
||||||
const { code: code1 } = compile({
|
const { code: code1 } = compile({
|
||||||
...input,
|
...input,
|
||||||
transformAssetUrls: {
|
transformAssetUrls: {
|
||||||
tags: { foo: ['bar'] }
|
tags: { foo: ['bar'] },
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(code1).toMatch(`import _imports_0 from 'baz'\n`)
|
expect(code1).toMatch(`import _imports_0 from 'baz'\n`)
|
||||||
|
|
||||||
|
@ -119,15 +119,15 @@ test('transform asset url options', () => {
|
||||||
const { code: code2 } = compile({
|
const { code: code2 } = compile({
|
||||||
...input,
|
...input,
|
||||||
transformAssetUrls: {
|
transformAssetUrls: {
|
||||||
foo: ['bar']
|
foo: ['bar'],
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(code2).toMatch(`import _imports_0 from 'baz'\n`)
|
expect(code2).toMatch(`import _imports_0 from 'baz'\n`)
|
||||||
|
|
||||||
// false option
|
// false option
|
||||||
const { code: code3 } = compile({
|
const { code: code3 } = compile({
|
||||||
...input,
|
...input,
|
||||||
transformAssetUrls: false
|
transformAssetUrls: false,
|
||||||
})
|
})
|
||||||
expect(code3).not.toMatch(`import _imports_0 from 'baz'\n`)
|
expect(code3).not.toMatch(`import _imports_0 from 'baz'\n`)
|
||||||
})
|
})
|
||||||
|
@ -139,12 +139,12 @@ test('source map', () => {
|
||||||
<div><p>{{ foobar }}</p></div>
|
<div><p>{{ foobar }}</p></div>
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ filename: 'example.vue', sourceMap: true }
|
{ filename: 'example.vue', sourceMap: true },
|
||||||
).descriptor.template!
|
).descriptor.template!
|
||||||
|
|
||||||
const { code, map } = compile({
|
const { code, map } = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content
|
source: template.content,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(map!.sources).toEqual([`example.vue`])
|
expect(map!.sources).toEqual([`example.vue`])
|
||||||
|
@ -152,7 +152,7 @@ test('source map', () => {
|
||||||
|
|
||||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar'))
|
consumer.originalPositionFor(getPositionInCode(code, 'foobar')),
|
||||||
).toMatchObject(getPositionInCode(template.content, `foobar`))
|
).toMatchObject(getPositionInCode(template.content, `foobar`))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -164,7 +164,7 @@ test('should work w/ AST from descriptor', () => {
|
||||||
`
|
`
|
||||||
const template = parse(source, {
|
const template = parse(source, {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
sourceMap: true
|
sourceMap: true,
|
||||||
}).descriptor.template!
|
}).descriptor.template!
|
||||||
|
|
||||||
expect(template.ast!.source).toBe(source)
|
expect(template.ast!.source).toBe(source)
|
||||||
|
@ -172,7 +172,7 @@ test('should work w/ AST from descriptor', () => {
|
||||||
const { code, map } = compile({
|
const { code, map } = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content,
|
source: template.content,
|
||||||
ast: template.ast
|
ast: template.ast,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(map!.sources).toEqual([`example.vue`])
|
expect(map!.sources).toEqual([`example.vue`])
|
||||||
|
@ -182,14 +182,14 @@ test('should work w/ AST from descriptor', () => {
|
||||||
|
|
||||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar'))
|
consumer.originalPositionFor(getPositionInCode(code, 'foobar')),
|
||||||
).toMatchObject(getPositionInCode(source, `foobar`))
|
).toMatchObject(getPositionInCode(source, `foobar`))
|
||||||
|
|
||||||
expect(code).toBe(
|
expect(code).toBe(
|
||||||
compile({
|
compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content
|
source: template.content,
|
||||||
}).code
|
}).code,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -201,7 +201,7 @@ test('should work w/ AST from descriptor in SSR mode', () => {
|
||||||
`
|
`
|
||||||
const template = parse(source, {
|
const template = parse(source, {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
sourceMap: true
|
sourceMap: true,
|
||||||
}).descriptor.template!
|
}).descriptor.template!
|
||||||
|
|
||||||
expect(template.ast!.source).toBe(source)
|
expect(template.ast!.source).toBe(source)
|
||||||
|
@ -210,7 +210,7 @@ test('should work w/ AST from descriptor in SSR mode', () => {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: '', // make sure it's actually using the AST instead of source
|
source: '', // make sure it's actually using the AST instead of source
|
||||||
ast: template.ast,
|
ast: template.ast,
|
||||||
ssr: true
|
ssr: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(map!.sources).toEqual([`example.vue`])
|
expect(map!.sources).toEqual([`example.vue`])
|
||||||
|
@ -220,15 +220,15 @@ test('should work w/ AST from descriptor in SSR mode', () => {
|
||||||
|
|
||||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||||
expect(
|
expect(
|
||||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar'))
|
consumer.originalPositionFor(getPositionInCode(code, 'foobar')),
|
||||||
).toMatchObject(getPositionInCode(source, `foobar`))
|
).toMatchObject(getPositionInCode(source, `foobar`))
|
||||||
|
|
||||||
expect(code).toBe(
|
expect(code).toBe(
|
||||||
compile({
|
compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content,
|
source: template.content,
|
||||||
ssr: true
|
ssr: true,
|
||||||
}).code
|
}).code,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -240,7 +240,7 @@ test('should not reuse AST if using custom compiler', () => {
|
||||||
`
|
`
|
||||||
const template = parse(source, {
|
const template = parse(source, {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
sourceMap: true
|
sourceMap: true,
|
||||||
}).descriptor.template!
|
}).descriptor.template!
|
||||||
|
|
||||||
const { code } = compile({
|
const { code } = compile({
|
||||||
|
@ -249,9 +249,9 @@ test('should not reuse AST if using custom compiler', () => {
|
||||||
ast: template.ast,
|
ast: template.ast,
|
||||||
compiler: {
|
compiler: {
|
||||||
parse: () => null as any,
|
parse: () => null as any,
|
||||||
// @ts-ignore
|
// @ts-expect-error
|
||||||
compile: input => ({ code: input })
|
compile: input => ({ code: input }),
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// what we really want to assert is that the `input` received by the custom
|
// what we really want to assert is that the `input` received by the custom
|
||||||
|
@ -267,7 +267,7 @@ test('should force re-parse on already transformed AST', () => {
|
||||||
`
|
`
|
||||||
const template = parse(source, {
|
const template = parse(source, {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
sourceMap: true
|
sourceMap: true,
|
||||||
}).descriptor.template!
|
}).descriptor.template!
|
||||||
|
|
||||||
// force set to empty, if this is reused then it won't generate proper code
|
// force set to empty, if this is reused then it won't generate proper code
|
||||||
|
@ -277,14 +277,14 @@ test('should force re-parse on already transformed AST', () => {
|
||||||
const { code } = compile({
|
const { code } = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: '',
|
source: '',
|
||||||
ast: template.ast
|
ast: template.ast,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toBe(
|
expect(code).toBe(
|
||||||
compile({
|
compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content
|
source: template.content,
|
||||||
}).code
|
}).code,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ test('should force re-parse with correct compiler in SSR mode', () => {
|
||||||
`
|
`
|
||||||
const template = parse(source, {
|
const template = parse(source, {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
sourceMap: true
|
sourceMap: true,
|
||||||
}).descriptor.template!
|
}).descriptor.template!
|
||||||
|
|
||||||
// force set to empty, if this is reused then it won't generate proper code
|
// force set to empty, if this is reused then it won't generate proper code
|
||||||
|
@ -307,15 +307,15 @@ test('should force re-parse with correct compiler in SSR mode', () => {
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: '',
|
source: '',
|
||||||
ast: template.ast,
|
ast: template.ast,
|
||||||
ssr: true
|
ssr: true,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toBe(
|
expect(code).toBe(
|
||||||
compile({
|
compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content,
|
source: template.content,
|
||||||
ssr: true
|
ssr: true,
|
||||||
}).code
|
}).code,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ test('template errors', () => {
|
||||||
const result = compile({
|
const result = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: `<div
|
source: `<div
|
||||||
:bar="a[" v-model="baz"/>`
|
:bar="a[" v-model="baz"/>`,
|
||||||
})
|
})
|
||||||
expect(result.errors).toMatchSnapshot()
|
expect(result.errors).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -335,20 +335,20 @@ test('preprocessor errors', () => {
|
||||||
div(class='class)
|
div(class='class)
|
||||||
</template>
|
</template>
|
||||||
`,
|
`,
|
||||||
{ filename: 'example.vue', sourceMap: true }
|
{ filename: 'example.vue', sourceMap: true },
|
||||||
).descriptor.template as SFCTemplateBlock
|
).descriptor.template as SFCTemplateBlock
|
||||||
|
|
||||||
const result = compile({
|
const result = compile({
|
||||||
filename: 'example.vue',
|
filename: 'example.vue',
|
||||||
source: template.content,
|
source: template.content,
|
||||||
preprocessLang: template.lang
|
preprocessLang: template.lang,
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(result.errors.length).toBe(1)
|
expect(result.errors.length).toBe(1)
|
||||||
const message = result.errors[0].toString()
|
const message = result.errors[0].toString()
|
||||||
expect(message).toMatch(`Error: example.vue:3:1`)
|
expect(message).toMatch(`Error: example.vue:3:1`)
|
||||||
expect(message).toMatch(
|
expect(message).toMatch(
|
||||||
`The end of the string reached with no closing bracket ) found.`
|
`The end of the string reached with no closing bracket ) found.`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -362,7 +362,7 @@ test('should generate the correct imports expression', () => {
|
||||||
<img src="./bar.svg"/>
|
<img src="./bar.svg"/>
|
||||||
</Comp>
|
</Comp>
|
||||||
`,
|
`,
|
||||||
ssr: true
|
ssr: true,
|
||||||
})
|
})
|
||||||
expect(code).toMatch(`_ssrRenderAttr(\"src\", _imports_1)`)
|
expect(code).toMatch(`_ssrRenderAttr(\"src\", _imports_1)`)
|
||||||
expect(code).toMatch(`_createVNode(\"img\", { src: _imports_1 })`)
|
expect(code).toMatch(`_createVNode(\"img\", { src: _imports_1 })`)
|
||||||
|
@ -384,7 +384,7 @@ test('should not hoist srcset URLs in SSR mode', () => {
|
||||||
</picture>
|
</picture>
|
||||||
</router-link>
|
</router-link>
|
||||||
`,
|
`,
|
||||||
ssr: true
|
ssr: true,
|
||||||
})
|
})
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -422,7 +422,7 @@ test('prefixing edge case for reused AST', () => {
|
||||||
id: 'xxx',
|
id: 'xxx',
|
||||||
filename: 'test.vue',
|
filename: 'test.vue',
|
||||||
ast: descriptor.template!.ast,
|
ast: descriptor.template!.ast,
|
||||||
source: descriptor.template!.content
|
source: descriptor.template!.content,
|
||||||
})
|
})
|
||||||
expect(code).not.toMatch(`_ctx.t`)
|
expect(code).not.toMatch(`_ctx.t`)
|
||||||
})
|
})
|
||||||
|
@ -436,7 +436,7 @@ interface Pos {
|
||||||
function getPositionInCode(
|
function getPositionInCode(
|
||||||
code: string,
|
code: string,
|
||||||
token: string,
|
token: string,
|
||||||
expectName: string | boolean = false
|
expectName: string | boolean = false,
|
||||||
): Pos {
|
): Pos {
|
||||||
const generatedOffset = code.indexOf(token)
|
const generatedOffset = code.indexOf(token)
|
||||||
let line = 1
|
let line = 1
|
||||||
|
@ -452,7 +452,7 @@ function getPositionInCode(
|
||||||
column:
|
column:
|
||||||
lastNewLinePos === -1
|
lastNewLinePos === -1
|
||||||
? generatedOffset
|
? generatedOffset
|
||||||
: generatedOffset - lastNewLinePos - 1
|
: generatedOffset - lastNewLinePos - 1,
|
||||||
}
|
}
|
||||||
if (expectName) {
|
if (expectName) {
|
||||||
res.name = typeof expectName === 'string' ? expectName : token
|
res.name = typeof expectName === 'string' ? expectName : token
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { compileStyle, parse } from '../src'
|
import { compileStyle, parse } from '../src'
|
||||||
import { mockId, compileSFCScript, assertCode } from './utils'
|
import { assertCode, compileSFCScript, mockId } from './utils'
|
||||||
|
|
||||||
describe('CSS vars injection', () => {
|
describe('CSS vars injection', () => {
|
||||||
test('generating correct code for nested paths', () => {
|
test('generating correct code for nested paths', () => {
|
||||||
|
@ -8,7 +8,7 @@ describe('CSS vars injection', () => {
|
||||||
`<style>div{
|
`<style>div{
|
||||||
color: v-bind(color);
|
color: v-bind(color);
|
||||||
font-size: v-bind('font.size');
|
font-size: v-bind('font.size');
|
||||||
}</style>`
|
}</style>`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||||
"${mockId}-color": (_ctx.color),
|
"${mockId}-color": (_ctx.color),
|
||||||
|
@ -32,7 +32,7 @@ describe('CSS vars injection', () => {
|
||||||
div {
|
div {
|
||||||
font-size: v-bind(size);
|
font-size: v-bind(size);
|
||||||
}
|
}
|
||||||
</style>`
|
</style>`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||||
"${mockId}-size": (_ctx.size)
|
"${mockId}-size": (_ctx.size)
|
||||||
|
@ -57,7 +57,7 @@ describe('CSS vars injection', () => {
|
||||||
font-size: v-bind(size);
|
font-size: v-bind(size);
|
||||||
border: v-bind(foo);
|
border: v-bind(foo);
|
||||||
}
|
}
|
||||||
</style>`
|
</style>`,
|
||||||
)
|
)
|
||||||
// should handle:
|
// should handle:
|
||||||
// 1. local const bindings
|
// 1. local const bindings
|
||||||
|
@ -69,7 +69,7 @@ describe('CSS vars injection', () => {
|
||||||
"${mockId}-foo": (__props.foo)
|
"${mockId}-foo": (__props.foo)
|
||||||
})`)
|
})`)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`
|
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`,
|
||||||
)
|
)
|
||||||
assertCode(content)
|
assertCode(content)
|
||||||
})
|
})
|
||||||
|
@ -85,7 +85,7 @@ describe('CSS vars injection', () => {
|
||||||
font-family: v-bind(フォント);
|
font-family: v-bind(フォント);
|
||||||
}`,
|
}`,
|
||||||
filename: 'test.css',
|
filename: 'test.css',
|
||||||
id: 'data-v-test'
|
id: 'data-v-test',
|
||||||
})
|
})
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
".foo {
|
".foo {
|
||||||
|
@ -106,7 +106,7 @@ describe('CSS vars injection', () => {
|
||||||
color: v-bind(color);
|
color: v-bind(color);
|
||||||
font-size: v-bind('font.size');
|
font-size: v-bind('font.size');
|
||||||
}</style>`,
|
}</style>`,
|
||||||
{ isProd: true }
|
{ isProd: true },
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||||
"4003f1a6": (_ctx.color),
|
"4003f1a6": (_ctx.color),
|
||||||
|
@ -120,7 +120,7 @@ describe('CSS vars injection', () => {
|
||||||
}`,
|
}`,
|
||||||
filename: 'test.css',
|
filename: 'test.css',
|
||||||
id: mockId,
|
id: mockId,
|
||||||
isProd: true
|
isProd: true,
|
||||||
})
|
})
|
||||||
expect(code).toMatchInlineSnapshot(`
|
expect(code).toMatchInlineSnapshot(`
|
||||||
".foo {
|
".foo {
|
||||||
|
@ -135,8 +135,8 @@ describe('CSS vars injection', () => {
|
||||||
assertCode(
|
assertCode(
|
||||||
compileSFCScript(
|
compileSFCScript(
|
||||||
`<script>const a = 1</script>\n` +
|
`<script>const a = 1</script>\n` +
|
||||||
`<style>div{ color: v-bind(color); }</style>`
|
`<style>div{ color: v-bind(color); }</style>`,
|
||||||
).content
|
).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -144,8 +144,8 @@ describe('CSS vars injection', () => {
|
||||||
assertCode(
|
assertCode(
|
||||||
compileSFCScript(
|
compileSFCScript(
|
||||||
`<script>export default { setup() {} }</script>\n` +
|
`<script>export default { setup() {} }</script>\n` +
|
||||||
`<style>div{ color: v-bind(color); }</style>`
|
`<style>div{ color: v-bind(color); }</style>`,
|
||||||
).content
|
).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -155,8 +155,8 @@ describe('CSS vars injection', () => {
|
||||||
`<script>
|
`<script>
|
||||||
// export default {}
|
// export default {}
|
||||||
export default {}
|
export default {}
|
||||||
</script>\n` + `<style>div{ color: v-bind(color); }</style>`
|
</script>\n` + `<style>div{ color: v-bind(color); }</style>`,
|
||||||
).content
|
).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -164,8 +164,8 @@ describe('CSS vars injection', () => {
|
||||||
assertCode(
|
assertCode(
|
||||||
compileSFCScript(
|
compileSFCScript(
|
||||||
`<script setup>const color = 'red'</script>\n` +
|
`<script setup>const color = 'red'</script>\n` +
|
||||||
`<style>div{ color: v-bind(color); }</style>`
|
`<style>div{ color: v-bind(color); }</style>`,
|
||||||
).content
|
).content,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ describe('CSS vars injection', () => {
|
||||||
div{ /* color: v-bind(color); */ width:20; }
|
div{ /* color: v-bind(color); */ width:20; }
|
||||||
div{ width: v-bind(width); }
|
div{ width: v-bind(width); }
|
||||||
/* comment */
|
/* comment */
|
||||||
</style>`
|
</style>`,
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(content).not.toMatch(`"${mockId}-color": (color)`)
|
expect(content).not.toMatch(`"${mockId}-color": (color)`)
|
||||||
|
@ -198,7 +198,7 @@ describe('CSS vars injection', () => {
|
||||||
p {
|
p {
|
||||||
color: v-bind(color);
|
color: v-bind(color);
|
||||||
}
|
}
|
||||||
</style>`
|
</style>`,
|
||||||
)
|
)
|
||||||
// color should only be injected once, even if it is twice in style
|
// color should only be injected once, even if it is twice in style
|
||||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||||
|
@ -229,7 +229,7 @@ describe('CSS vars injection', () => {
|
||||||
p {
|
p {
|
||||||
color: v-bind(((a + b)) / (2 * a));
|
color: v-bind(((a + b)) / (2 * a));
|
||||||
}
|
}
|
||||||
</style>`
|
</style>`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||||
"${mockId}-foo": (_unref(foo)),
|
"${mockId}-foo": (_unref(foo)),
|
||||||
|
@ -243,7 +243,7 @@ describe('CSS vars injection', () => {
|
||||||
// #6022
|
// #6022
|
||||||
test('should be able to parse incomplete expressions', () => {
|
test('should be able to parse incomplete expressions', () => {
|
||||||
const {
|
const {
|
||||||
descriptor: { cssVars }
|
descriptor: { cssVars },
|
||||||
} = parse(
|
} = parse(
|
||||||
`<script setup>let xxx = 1</script>
|
`<script setup>let xxx = 1</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
@ -251,7 +251,7 @@ describe('CSS vars injection', () => {
|
||||||
font-weight: v-bind("count.toString(");
|
font-weight: v-bind("count.toString(");
|
||||||
font-weight: v-bind(xxx);
|
font-weight: v-bind(xxx);
|
||||||
}
|
}
|
||||||
</style>`
|
</style>`,
|
||||||
)
|
)
|
||||||
expect(cssVars).toMatchObject([`count.toString(`, `xxx`])
|
expect(cssVars).toMatchObject([`count.toString(`, `xxx`])
|
||||||
})
|
})
|
||||||
|
@ -266,10 +266,10 @@ describe('CSS vars injection', () => {
|
||||||
label {
|
label {
|
||||||
background: v-bind(background);
|
background: v-bind(background);
|
||||||
}
|
}
|
||||||
</style>`
|
</style>`,
|
||||||
)
|
)
|
||||||
expect(content).toMatch(
|
expect(content).toMatch(
|
||||||
`export default {\n setup(__props, { expose: __expose }) {\n __expose();\n\n_useCssVars(_ctx => ({\n "xxxxxxxx-background": (_unref(background))\n}))`
|
`export default {\n setup(__props, { expose: __expose }) {\n __expose();\n\n_useCssVars(_ctx => ({\n "xxxxxxxx-background": (_unref(background))\n}))`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -287,9 +287,9 @@ describe('CSS vars injection', () => {
|
||||||
{
|
{
|
||||||
inlineTemplate: true,
|
inlineTemplate: true,
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
ssr: true
|
ssr: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch(`_useCssVars`)
|
expect(content).not.toMatch(`_useCssVars`)
|
||||||
})
|
})
|
||||||
|
@ -308,9 +308,9 @@ describe('CSS vars injection', () => {
|
||||||
{
|
{
|
||||||
inlineTemplate: false,
|
inlineTemplate: false,
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
ssr: true
|
ssr: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch(`_useCssVars`)
|
expect(content).not.toMatch(`_useCssVars`)
|
||||||
})
|
})
|
||||||
|
@ -333,9 +333,9 @@ describe('CSS vars injection', () => {
|
||||||
</style>`,
|
</style>`,
|
||||||
{
|
{
|
||||||
templateOptions: {
|
templateOptions: {
|
||||||
ssr: true
|
ssr: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(content).not.toMatch(`_useCssVars`)
|
expect(content).not.toMatch(`_useCssVars`)
|
||||||
})
|
})
|
||||||
|
|
|
@ -37,7 +37,7 @@ font-weight: bold;
|
||||||
}
|
}
|
||||||
</style>`
|
</style>`
|
||||||
const {
|
const {
|
||||||
descriptor: { styles }
|
descriptor: { styles },
|
||||||
} = parse(src)
|
} = parse(src)
|
||||||
|
|
||||||
expect(styles[0].map).not.toBeUndefined()
|
expect(styles[0].map).not.toBeUndefined()
|
||||||
|
@ -69,7 +69,7 @@ font-weight: bold;
|
||||||
// Padding determines how many blank lines will there be before the style block
|
// Padding determines how many blank lines will there be before the style block
|
||||||
const padding = Math.round(Math.random() * 10)
|
const padding = Math.round(Math.random() * 10)
|
||||||
const script = parse(
|
const script = parse(
|
||||||
`${'\n'.repeat(padding)}<script>\nconsole.log(1)\n }\n</script>\n`
|
`${'\n'.repeat(padding)}<script>\nconsole.log(1)\n }\n</script>\n`,
|
||||||
).descriptor.script
|
).descriptor.script
|
||||||
|
|
||||||
expect(script!.map).not.toBeUndefined()
|
expect(script!.map).not.toBeUndefined()
|
||||||
|
@ -88,7 +88,7 @@ font-weight: bold;
|
||||||
h1 foo
|
h1 foo
|
||||||
div bar
|
div bar
|
||||||
span baz
|
span baz
|
||||||
</template>\n`
|
</template>\n`,
|
||||||
).descriptor.template!
|
).descriptor.template!
|
||||||
|
|
||||||
expect(template.map).not.toBeUndefined()
|
expect(template.map).not.toBeUndefined()
|
||||||
|
@ -103,7 +103,7 @@ font-weight: bold;
|
||||||
test('custom block', () => {
|
test('custom block', () => {
|
||||||
const padding = Math.round(Math.random() * 10)
|
const padding = Math.round(Math.random() * 10)
|
||||||
const custom = parse(
|
const custom = parse(
|
||||||
`${'\n'.repeat(padding)}<i18n>\n{\n "greeting": "hello"\n}\n</i18n>\n`
|
`${'\n'.repeat(padding)}<i18n>\n{\n "greeting": "hello"\n}\n</i18n>\n`,
|
||||||
).descriptor.customBlocks[0]
|
).descriptor.customBlocks[0]
|
||||||
|
|
||||||
expect(custom!.map).not.toBeUndefined()
|
expect(custom!.map).not.toBeUndefined()
|
||||||
|
@ -138,42 +138,42 @@ h1 { color: red }
|
||||||
|
|
||||||
const padTrue = parse(content.trim(), { pad: true }).descriptor
|
const padTrue = parse(content.trim(), { pad: true }).descriptor
|
||||||
expect(padTrue.script!.content).toBe(
|
expect(padTrue.script!.content).toBe(
|
||||||
Array(3 + 1).join('//\n') + '\nexport default {}\n'
|
Array(3 + 1).join('//\n') + '\nexport default {}\n',
|
||||||
)
|
)
|
||||||
expect(padTrue.styles[0].content).toBe(
|
expect(padTrue.styles[0].content).toBe(
|
||||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n'
|
Array(6 + 1).join('\n') + '\nh1 { color: red }\n',
|
||||||
)
|
)
|
||||||
expect(padTrue.customBlocks[0].content).toBe(
|
expect(padTrue.customBlocks[0].content).toBe(
|
||||||
Array(9 + 1).join('\n') + '\n{ "greeting": "hello" }\n'
|
Array(9 + 1).join('\n') + '\n{ "greeting": "hello" }\n',
|
||||||
)
|
)
|
||||||
|
|
||||||
const padLine = parse(content.trim(), { pad: 'line' }).descriptor
|
const padLine = parse(content.trim(), { pad: 'line' }).descriptor
|
||||||
expect(padLine.script!.content).toBe(
|
expect(padLine.script!.content).toBe(
|
||||||
Array(3 + 1).join('//\n') + '\nexport default {}\n'
|
Array(3 + 1).join('//\n') + '\nexport default {}\n',
|
||||||
)
|
)
|
||||||
expect(padLine.styles[0].content).toBe(
|
expect(padLine.styles[0].content).toBe(
|
||||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n'
|
Array(6 + 1).join('\n') + '\nh1 { color: red }\n',
|
||||||
)
|
)
|
||||||
expect(padLine.customBlocks[0].content).toBe(
|
expect(padLine.customBlocks[0].content).toBe(
|
||||||
Array(9 + 1).join('\n') + '\n{ "greeting": "hello" }\n'
|
Array(9 + 1).join('\n') + '\n{ "greeting": "hello" }\n',
|
||||||
)
|
)
|
||||||
|
|
||||||
const padSpace = parse(content.trim(), { pad: 'space' }).descriptor
|
const padSpace = parse(content.trim(), { pad: 'space' }).descriptor
|
||||||
expect(padSpace.script!.content).toBe(
|
expect(padSpace.script!.content).toBe(
|
||||||
`<template>\n<div></div>\n</template>\n<script>`.replace(/./g, ' ') +
|
`<template>\n<div></div>\n</template>\n<script>`.replace(/./g, ' ') +
|
||||||
'\nexport default {}\n'
|
'\nexport default {}\n',
|
||||||
)
|
)
|
||||||
expect(padSpace.styles[0].content).toBe(
|
expect(padSpace.styles[0].content).toBe(
|
||||||
`<template>\n<div></div>\n</template>\n<script>\nexport default {}\n</script>\n<style>`.replace(
|
`<template>\n<div></div>\n</template>\n<script>\nexport default {}\n</script>\n<style>`.replace(
|
||||||
/./g,
|
/./g,
|
||||||
' '
|
' ',
|
||||||
) + '\nh1 { color: red }\n'
|
) + '\nh1 { color: red }\n',
|
||||||
)
|
)
|
||||||
expect(padSpace.customBlocks[0].content).toBe(
|
expect(padSpace.customBlocks[0].content).toBe(
|
||||||
`<template>\n<div></div>\n</template>\n<script>\nexport default {}\n</script>\n<style>\nh1 { color: red }\n</style>\n<i18n>`.replace(
|
`<template>\n<div></div>\n</template>\n<script>\nexport default {}\n</script>\n<style>\nh1 { color: red }\n</style>\n<i18n>`.replace(
|
||||||
/./g,
|
/./g,
|
||||||
' '
|
' ',
|
||||||
) + '\n{ "greeting": "hello" }\n'
|
) + '\n{ "greeting": "hello" }\n',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -187,8 +187,8 @@ h1 { color: red }
|
||||||
end: {
|
end: {
|
||||||
line: 3,
|
line: 3,
|
||||||
column: 1,
|
column: 1,
|
||||||
offset: 10 + content.length
|
offset: 10 + content.length,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -198,7 +198,7 @@ h1 { color: red }
|
||||||
expect(descriptor.template!.content).toBeFalsy()
|
expect(descriptor.template!.content).toBeFalsy()
|
||||||
expect(descriptor.template!.loc).toMatchObject({
|
expect(descriptor.template!.loc).toMatchObject({
|
||||||
start: { line: 1, column: 12, offset: 11 },
|
start: { line: 1, column: 12, offset: 11 },
|
||||||
end: { line: 1, column: 12, offset: 11 }
|
end: { line: 1, column: 12, offset: 11 },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ h1 { color: red }
|
||||||
expect(descriptor.template!.content).toBeFalsy()
|
expect(descriptor.template!.content).toBeFalsy()
|
||||||
expect(descriptor.template!.loc).toMatchObject({
|
expect(descriptor.template!.loc).toMatchObject({
|
||||||
start: { line: 1, column: 11, offset: 10 },
|
start: { line: 1, column: 11, offset: 10 },
|
||||||
end: { line: 1, column: 11, offset: 10 }
|
end: { line: 1, column: 11, offset: 10 },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -219,7 +219,7 @@ h1 { color: red }
|
||||||
expect(parse(`<style> \n\t </style>`).descriptor.styles.length).toBe(0)
|
expect(parse(`<style> \n\t </style>`).descriptor.styles.length).toBe(0)
|
||||||
expect(parse(`<custom/>`).descriptor.customBlocks.length).toBe(0)
|
expect(parse(`<custom/>`).descriptor.customBlocks.length).toBe(0)
|
||||||
expect(
|
expect(
|
||||||
parse(`<custom> \n\t </custom>`).descriptor.customBlocks.length
|
parse(`<custom> \n\t </custom>`).descriptor.customBlocks.length,
|
||||||
).toBe(0)
|
).toBe(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -239,19 +239,19 @@ h1 { color: red }
|
||||||
const { descriptor } = parse(
|
const { descriptor } = parse(
|
||||||
`<script></script>\n<script setup>\n</script>`,
|
`<script></script>\n<script setup>\n</script>`,
|
||||||
{
|
{
|
||||||
ignoreEmpty: false
|
ignoreEmpty: false,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(descriptor.script).toBeTruthy()
|
expect(descriptor.script).toBeTruthy()
|
||||||
expect(descriptor.script!.loc).toMatchObject({
|
expect(descriptor.script!.loc).toMatchObject({
|
||||||
start: { line: 1, column: 9, offset: 8 },
|
start: { line: 1, column: 9, offset: 8 },
|
||||||
end: { line: 1, column: 9, offset: 8 }
|
end: { line: 1, column: 9, offset: 8 },
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(descriptor.scriptSetup).toBeTruthy()
|
expect(descriptor.scriptSetup).toBeTruthy()
|
||||||
expect(descriptor.scriptSetup!.loc).toMatchObject({
|
expect(descriptor.scriptSetup!.loc).toMatchObject({
|
||||||
start: { line: 2, column: 15, offset: 32 },
|
start: { line: 2, column: 15, offset: 32 },
|
||||||
end: { line: 3, column: 1, offset: 33 }
|
end: { line: 3, column: 1, offset: 33 },
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -267,7 +267,7 @@ h1 { color: red }
|
||||||
test('treat empty lang attribute as the html', () => {
|
test('treat empty lang attribute as the html', () => {
|
||||||
const content = `<div><template v-if="ok">ok</template></div>`
|
const content = `<div><template v-if="ok">ok</template></div>`
|
||||||
const { descriptor, errors } = parse(
|
const { descriptor, errors } = parse(
|
||||||
`<template lang="">${content}</template>`
|
`<template lang="">${content}</template>`,
|
||||||
)
|
)
|
||||||
expect(descriptor.template!.content).toBe(content)
|
expect(descriptor.template!.content).toBe(content)
|
||||||
expect(errors.length).toBe(0)
|
expect(errors.length).toBe(0)
|
||||||
|
@ -277,7 +277,7 @@ h1 { color: red }
|
||||||
test('template with preprocessor lang should be treated as plain text', () => {
|
test('template with preprocessor lang should be treated as plain text', () => {
|
||||||
const content = `p(v-if="1 < 2") test <div/>`
|
const content = `p(v-if="1 < 2") test <div/>`
|
||||||
const { descriptor, errors } = parse(
|
const { descriptor, errors } = parse(
|
||||||
`<template lang="pug">` + content + `</template>`
|
`<template lang="pug">` + content + `</template>`,
|
||||||
)
|
)
|
||||||
expect(errors.length).toBe(0)
|
expect(errors.length).toBe(0)
|
||||||
expect(descriptor.template!.content).toBe(content)
|
expect(descriptor.template!.content).toBe(content)
|
||||||
|
@ -301,17 +301,17 @@ h1 { color: red }
|
||||||
expect(parse(`<template>hi</template>`).descriptor.slotted).toBe(false)
|
expect(parse(`<template>hi</template>`).descriptor.slotted).toBe(false)
|
||||||
expect(
|
expect(
|
||||||
parse(`<template>hi</template><style>h1{color:red;}</style>`).descriptor
|
parse(`<template>hi</template><style>h1{color:red;}</style>`).descriptor
|
||||||
.slotted
|
.slotted,
|
||||||
).toBe(false)
|
).toBe(false)
|
||||||
expect(
|
expect(
|
||||||
parse(
|
parse(
|
||||||
`<template>hi</template><style scoped>:slotted(h1){color:red;}</style>`
|
`<template>hi</template><style scoped>:slotted(h1){color:red;}</style>`,
|
||||||
).descriptor.slotted
|
).descriptor.slotted,
|
||||||
).toBe(true)
|
).toBe(true)
|
||||||
expect(
|
expect(
|
||||||
parse(
|
parse(
|
||||||
`<template>hi</template><style scoped>::v-slotted(h1){color:red;}</style>`
|
`<template>hi</template><style scoped>::v-slotted(h1){color:red;}</style>`,
|
||||||
).descriptor.slotted
|
).descriptor.slotted,
|
||||||
).toBe(true)
|
).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -332,8 +332,8 @@ h1 { color: red }
|
||||||
options.onError!(new Error('foo') as any)
|
options.onError!(new Error('foo') as any)
|
||||||
return createRoot([])
|
return createRoot([])
|
||||||
},
|
},
|
||||||
compile: baseCompile
|
compile: baseCompile,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
expect(errors.length).toBe(2)
|
expect(errors.length).toBe(2)
|
||||||
// error thrown by the custom parse
|
// error thrown by the custom parse
|
||||||
|
@ -344,7 +344,7 @@ h1 { color: red }
|
||||||
|
|
||||||
test('treat custom blocks as raw text', () => {
|
test('treat custom blocks as raw text', () => {
|
||||||
const { errors, descriptor } = parse(
|
const { errors, descriptor } = parse(
|
||||||
`<template><input></template><foo> <-& </foo>`
|
`<template><input></template><foo> <-& </foo>`,
|
||||||
)
|
)
|
||||||
expect(errors.length).toBe(0)
|
expect(errors.length).toBe(0)
|
||||||
expect(descriptor.customBlocks[0].content).toBe(` <-& `)
|
expect(descriptor.customBlocks[0].content).toBe(` <-& `)
|
||||||
|
@ -358,7 +358,7 @@ h1 { color: red }
|
||||||
test('should only allow single template element', () => {
|
test('should only allow single template element', () => {
|
||||||
assertWarning(
|
assertWarning(
|
||||||
parse(`<template><div/></template><template><div/></template>`).errors,
|
parse(`<template><div/></template><template><div/></template>`).errors,
|
||||||
`Single file component can contain only one <template> element`
|
`Single file component can contain only one <template> element`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -366,24 +366,24 @@ h1 { color: red }
|
||||||
assertWarning(
|
assertWarning(
|
||||||
parse(`<script>console.log(1)</script><script>console.log(1)</script>`)
|
parse(`<script>console.log(1)</script><script>console.log(1)</script>`)
|
||||||
.errors,
|
.errors,
|
||||||
`Single file component can contain only one <script> element`
|
`Single file component can contain only one <script> element`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should only allow single script setup element', () => {
|
test('should only allow single script setup element', () => {
|
||||||
assertWarning(
|
assertWarning(
|
||||||
parse(
|
parse(
|
||||||
`<script setup>console.log(1)</script><script setup>console.log(1)</script>`
|
`<script setup>console.log(1)</script><script setup>console.log(1)</script>`,
|
||||||
).errors,
|
).errors,
|
||||||
`Single file component can contain only one <script setup> element`
|
`Single file component can contain only one <script setup> element`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
test('should not warn script & script setup', () => {
|
test('should not warn script & script setup', () => {
|
||||||
expect(
|
expect(
|
||||||
parse(
|
parse(
|
||||||
`<script setup>console.log(1)</script><script>console.log(1)</script>`
|
`<script setup>console.log(1)</script><script>console.log(1)</script>`,
|
||||||
).errors.length
|
).errors.length,
|
||||||
).toBe(0)
|
).toBe(0)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -391,7 +391,7 @@ h1 { color: red }
|
||||||
test('should throw error if no <template> or <script> is present', () => {
|
test('should throw error if no <template> or <script> is present', () => {
|
||||||
assertWarning(
|
assertWarning(
|
||||||
parse(`import { ref } from 'vue'`).errors,
|
parse(`import { ref } from 'vue'`).errors,
|
||||||
`At least one <template> or <script> is required in a single file component`
|
`At least one <template> or <script> is required in a single file component`,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
|
@ -11,7 +11,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
|
|
||||||
test('rewrite export default', () => {
|
test('rewrite export default', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(`export default {}`, 'script')
|
rewriteDefault(`export default {}`, 'script'),
|
||||||
).toMatchInlineSnapshot(`"const script = {}"`)
|
).toMatchInlineSnapshot(`"const script = {}"`)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`const a = 1 \n export { a as b, a as default, a as c}`,
|
`const a = 1 \n export { a as b, a as default, a as c}`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const a = 1
|
"const a = 1
|
||||||
export { a as b, a as c}
|
export { a as b, a as c}
|
||||||
|
@ -38,8 +38,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`const a = 1 \n export { a as b, a as default , a as c}`,
|
`const a = 1 \n export { a as b, a as default , a as c}`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const a = 1
|
"const a = 1
|
||||||
export { a as b, a as c}
|
export { a as b, a as c}
|
||||||
|
@ -49,8 +49,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`const a = 1 \n export { a as b } \n export { a as default, a as c }`,
|
`const a = 1 \n export { a as b } \n export { a as default, a as c }`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const a = 1
|
"const a = 1
|
||||||
export { a as b }
|
export { a as b }
|
||||||
|
@ -69,7 +69,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
|
|
||||||
test('export named default multiline', () => {
|
test('export named default multiline', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(`let App = {}\n export {\nApp as default\n}`, '_sfc_main')
|
rewriteDefault(`let App = {}\n export {\nApp as default\n}`, '_sfc_main'),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"let App = {}
|
"let App = {}
|
||||||
export {
|
export {
|
||||||
|
@ -84,8 +84,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`const a = 1 \n export {\n a as b,\n a as default,\n a as c}\n` +
|
`const a = 1 \n export {\n a as b,\n a as default,\n a as c}\n` +
|
||||||
`// export { myFunction as default }`,
|
`// export { myFunction as default }`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const a = 1
|
"const a = 1
|
||||||
export {
|
export {
|
||||||
|
@ -100,8 +100,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`const a = 1 \n export {\n a as b,\n a as default ,\n a as c}\n` +
|
`const a = 1 \n export {\n a as b,\n a as default ,\n a as c}\n` +
|
||||||
`// export { myFunction as default }`,
|
`// export { myFunction as default }`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const a = 1
|
"const a = 1
|
||||||
export {
|
export {
|
||||||
|
@ -115,7 +115,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
|
|
||||||
test(`export { default } from '...'`, async () => {
|
test(`export { default } from '...'`, async () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(`export { default, foo } from './index.js'`, 'script')
|
rewriteDefault(`export { default, foo } from './index.js'`, 'script'),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||||
export { foo } from './index.js'
|
export { foo } from './index.js'
|
||||||
|
@ -123,7 +123,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(`export { default , foo } from './index.js'`, 'script')
|
rewriteDefault(`export { default , foo } from './index.js'`, 'script'),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||||
export { foo } from './index.js'
|
export { foo } from './index.js'
|
||||||
|
@ -131,7 +131,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
`)
|
`)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(`export { foo, default } from './index.js'`, 'script')
|
rewriteDefault(`export { foo, default } from './index.js'`, 'script'),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||||
export { foo, } from './index.js'
|
export { foo, } from './index.js'
|
||||||
|
@ -141,8 +141,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`export { foo as default, bar } from './index.js'`,
|
`export { foo as default, bar } from './index.js'`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||||
export { bar } from './index.js'
|
export { bar } from './index.js'
|
||||||
|
@ -152,8 +152,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`export { foo as default , bar } from './index.js'`,
|
`export { foo as default , bar } from './index.js'`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||||
export { bar } from './index.js'
|
export { bar } from './index.js'
|
||||||
|
@ -163,8 +163,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`export { bar, foo as default } from './index.js'`,
|
`export { bar, foo as default } from './index.js'`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||||
export { bar, } from './index.js'
|
export { bar, } from './index.js'
|
||||||
|
@ -174,8 +174,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`export { foo as default } from './index.js' \n const foo = 1`,
|
`export { foo as default } from './index.js' \n const foo = 1`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||||
export { } from './index.js'
|
export { } from './index.js'
|
||||||
|
@ -186,8 +186,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`const a = 1 \nexport { a as default } from 'xxx'`,
|
`const a = 1 \nexport { a as default } from 'xxx'`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"import { a as __VUE_DEFAULT__ } from 'xxx'
|
"import { a as __VUE_DEFAULT__ } from 'xxx'
|
||||||
const a = 1
|
const a = 1
|
||||||
|
@ -206,7 +206,10 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
|
|
||||||
test('export default class w/ comments', async () => {
|
test('export default class w/ comments', async () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(`// export default\nexport default class Foo {}`, 'script')
|
rewriteDefault(
|
||||||
|
`// export default\nexport default class Foo {}`,
|
||||||
|
'script',
|
||||||
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"// export default
|
"// export default
|
||||||
class Foo {}
|
class Foo {}
|
||||||
|
@ -218,8 +221,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`export default {}\n` + `// export default class Foo {}`,
|
`export default {}\n` + `// export default class Foo {}`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const script = {}
|
"const script = {}
|
||||||
// export default class Foo {}"
|
// export default class Foo {}"
|
||||||
|
@ -230,8 +233,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`/*\nexport default class Foo {}*/\n` + `export default class Bar {}`,
|
`/*\nexport default class Foo {}*/\n` + `export default class Bar {}`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"/*
|
"/*
|
||||||
export default class Foo {}*/
|
export default class Foo {}*/
|
||||||
|
@ -243,8 +246,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
test('@Component\nexport default class', async () => {
|
test('@Component\nexport default class', async () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(`@Component\nexport default class Foo {}`, 'script', [
|
rewriteDefault(`@Component\nexport default class Foo {}`, 'script', [
|
||||||
'decorators-legacy'
|
'decorators-legacy',
|
||||||
])
|
]),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"@Component class Foo {}
|
"@Component class Foo {}
|
||||||
const script = Foo"
|
const script = Foo"
|
||||||
|
@ -256,8 +259,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`// export default\n@Component\nexport default class Foo {}`,
|
`// export default\n@Component\nexport default class Foo {}`,
|
||||||
'script',
|
'script',
|
||||||
['decorators-legacy']
|
['decorators-legacy'],
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"// export default
|
"// export default
|
||||||
@Component class Foo {}
|
@Component class Foo {}
|
||||||
|
@ -269,8 +272,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
expect(
|
expect(
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`export default {}\n` + `// @Component\n// export default class Foo {}`,
|
`export default {}\n` + `// @Component\n// export default class Foo {}`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"const script = {}
|
"const script = {}
|
||||||
// @Component
|
// @Component
|
||||||
|
@ -283,8 +286,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
||||||
rewriteDefault(
|
rewriteDefault(
|
||||||
`/*\n@Component\nexport default class Foo {}*/\n` +
|
`/*\n@Component\nexport default class Foo {}*/\n` +
|
||||||
`export default class Bar {}`,
|
`export default class Bar {}`,
|
||||||
'script'
|
'script',
|
||||||
)
|
),
|
||||||
).toMatchInlineSnapshot(`
|
).toMatchInlineSnapshot(`
|
||||||
"/*
|
"/*
|
||||||
@Component
|
@Component
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import {
|
import {
|
||||||
generate,
|
type TransformOptions,
|
||||||
baseParse,
|
baseParse,
|
||||||
|
generate,
|
||||||
transform,
|
transform,
|
||||||
TransformOptions
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import {
|
import {
|
||||||
transformAssetUrl,
|
type AssetURLOptions,
|
||||||
createAssetUrlTransformWithOptions,
|
createAssetUrlTransformWithOptions,
|
||||||
AssetURLOptions,
|
normalizeOptions,
|
||||||
normalizeOptions
|
transformAssetUrl,
|
||||||
} from '../src/template/transformAssetUrl'
|
} from '../src/template/transformAssetUrl'
|
||||||
import { transformElement } from '../../compiler-core/src/transforms/transformElement'
|
import { transformElement } from '../../compiler-core/src/transforms/transformElement'
|
||||||
import { transformBind } from '../../compiler-core/src/transforms/vBind'
|
import { transformBind } from '../../compiler-core/src/transforms/vBind'
|
||||||
|
@ -17,7 +17,7 @@ import { stringifyStatic } from '../../compiler-dom/src/transforms/stringifyStat
|
||||||
function compileWithAssetUrls(
|
function compileWithAssetUrls(
|
||||||
template: string,
|
template: string,
|
||||||
options?: AssetURLOptions,
|
options?: AssetURLOptions,
|
||||||
transformOptions?: TransformOptions
|
transformOptions?: TransformOptions,
|
||||||
) {
|
) {
|
||||||
const ast = baseParse(template)
|
const ast = baseParse(template)
|
||||||
const t = options
|
const t = options
|
||||||
|
@ -26,9 +26,9 @@ function compileWithAssetUrls(
|
||||||
transform(ast, {
|
transform(ast, {
|
||||||
nodeTransforms: [t, transformElement],
|
nodeTransforms: [t, transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
},
|
},
|
||||||
...transformOptions
|
...transformOptions,
|
||||||
})
|
})
|
||||||
return generate(ast, { mode: 'module' })
|
return generate(ast, { mode: 'module' })
|
||||||
}
|
}
|
||||||
|
@ -57,8 +57,8 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
'<use href="~@svg/file.svg#fragment"></use>',
|
'<use href="~@svg/file.svg#fragment"></use>',
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
hoistStatic: true
|
hoistStatic: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(result.code).toMatchSnapshot()
|
expect(result.code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -79,8 +79,8 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
`<img src="~bar.png"></img>` + // -> still converts to import
|
`<img src="~bar.png"></img>` + // -> still converts to import
|
||||||
`<img src="@theme/bar.png"></img>`, // -> still converts to import
|
`<img src="@theme/bar.png"></img>`, // -> still converts to import
|
||||||
{
|
{
|
||||||
base: '/foo'
|
base: '/foo',
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`import _imports_0 from 'bar.png'`)
|
expect(code).toMatch(`import _imports_0 from 'bar.png'`)
|
||||||
expect(code).toMatch(`import _imports_1 from '@theme/bar.png'`)
|
expect(code).toMatch(`import _imports_1 from '@theme/bar.png'`)
|
||||||
|
@ -94,8 +94,8 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
`<img src="https://foo.bar/baz.png"/>` +
|
`<img src="https://foo.bar/baz.png"/>` +
|
||||||
`<img src="//foo.bar/baz.png"/>`,
|
`<img src="//foo.bar/baz.png"/>`,
|
||||||
{
|
{
|
||||||
includeAbsolute: true
|
includeAbsolute: true,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
@ -108,7 +108,7 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
<circle id="myCircle" cx="0" cy="0" r="5" />
|
<circle id="myCircle" cx="0" cy="0" r="5" />
|
||||||
</defs>
|
</defs>
|
||||||
<use x="5" y="5" xlink:href="#myCircle" />
|
<use x="5" y="5" xlink:href="#myCircle" />
|
||||||
</svg>`
|
</svg>`,
|
||||||
)
|
)
|
||||||
// should not remove it
|
// should not remove it
|
||||||
expect(code).toMatch(`"xlink:href": "#myCircle"`)
|
expect(code).toMatch(`"xlink:href": "#myCircle"`)
|
||||||
|
@ -116,7 +116,7 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
|
|
||||||
test('should allow for full base URLs, with paths', () => {
|
test('should allow for full base URLs, with paths', () => {
|
||||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||||
base: 'http://localhost:3000/src/'
|
base: 'http://localhost:3000/src/',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -124,7 +124,7 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
|
|
||||||
test('should allow for full base URLs, without paths', () => {
|
test('should allow for full base URLs, without paths', () => {
|
||||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||||
base: 'http://localhost:3000'
|
base: 'http://localhost:3000',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -132,7 +132,7 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
|
|
||||||
test('should allow for full base URLs, without port', () => {
|
test('should allow for full base URLs, without port', () => {
|
||||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||||
base: 'http://localhost'
|
base: 'http://localhost',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -140,7 +140,7 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
|
|
||||||
test('should allow for full base URLs, without protocol', () => {
|
test('should allow for full base URLs, without protocol', () => {
|
||||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||||
base: '//localhost'
|
base: '//localhost',
|
||||||
})
|
})
|
||||||
|
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -156,12 +156,12 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
`<img src="./bar.png"/>` +
|
`<img src="./bar.png"/>` +
|
||||||
`</div>`,
|
`</div>`,
|
||||||
{
|
{
|
||||||
includeAbsolute: true
|
includeAbsolute: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
transformHoist: stringifyStatic
|
transformHoist: stringifyStatic,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`_createStaticVNode`)
|
expect(code).toMatch(`_createStaticVNode`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -171,12 +171,12 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
const { code } = compileWithAssetUrls(
|
const { code } = compileWithAssetUrls(
|
||||||
`<div><img src="/foo bar.png"/></div>`,
|
`<div><img src="/foo bar.png"/></div>`,
|
||||||
{
|
{
|
||||||
includeAbsolute: true
|
includeAbsolute: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
transformHoist: stringifyStatic
|
transformHoist: stringifyStatic,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`_createElementVNode`)
|
expect(code).toMatch(`_createElementVNode`)
|
||||||
expect(code).toContain(`import _imports_0 from '/foo bar.png'`)
|
expect(code).toContain(`import _imports_0 from '/foo bar.png'`)
|
||||||
|
@ -186,12 +186,12 @@ describe('compiler sfc: transform asset url', () => {
|
||||||
const { code } = compileWithAssetUrls(
|
const { code } = compileWithAssetUrls(
|
||||||
`<div><img src="./foo bar.png"/></div>`,
|
`<div><img src="./foo bar.png"/></div>`,
|
||||||
{
|
{
|
||||||
includeAbsolute: true
|
includeAbsolute: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
transformHoist: stringifyStatic
|
transformHoist: stringifyStatic,
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
expect(code).toMatch(`_createElementVNode`)
|
expect(code).toMatch(`_createElementVNode`)
|
||||||
expect(code).toContain(`import _imports_0 from './foo bar.png'`)
|
expect(code).toContain(`import _imports_0 from './foo bar.png'`)
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
import {
|
import {
|
||||||
generate,
|
type TransformOptions,
|
||||||
baseParse,
|
baseParse,
|
||||||
|
generate,
|
||||||
transform,
|
transform,
|
||||||
TransformOptions
|
|
||||||
} from '@vue/compiler-core'
|
} from '@vue/compiler-core'
|
||||||
import {
|
import {
|
||||||
|
createSrcsetTransformWithOptions,
|
||||||
transformSrcset,
|
transformSrcset,
|
||||||
createSrcsetTransformWithOptions
|
|
||||||
} from '../src/template/transformSrcset'
|
} from '../src/template/transformSrcset'
|
||||||
import { transformElement } from '../../compiler-core/src/transforms/transformElement'
|
import { transformElement } from '../../compiler-core/src/transforms/transformElement'
|
||||||
import { transformBind } from '../../compiler-core/src/transforms/vBind'
|
import { transformBind } from '../../compiler-core/src/transforms/vBind'
|
||||||
import {
|
import {
|
||||||
AssetURLOptions,
|
type AssetURLOptions,
|
||||||
normalizeOptions
|
normalizeOptions,
|
||||||
} from '../src/template/transformAssetUrl'
|
} from '../src/template/transformAssetUrl'
|
||||||
import { stringifyStatic } from '../../compiler-dom/src/transforms/stringifyStatic'
|
import { stringifyStatic } from '../../compiler-dom/src/transforms/stringifyStatic'
|
||||||
|
|
||||||
function compileWithSrcset(
|
function compileWithSrcset(
|
||||||
template: string,
|
template: string,
|
||||||
options?: AssetURLOptions,
|
options?: AssetURLOptions,
|
||||||
transformOptions?: TransformOptions
|
transformOptions?: TransformOptions,
|
||||||
) {
|
) {
|
||||||
const ast = baseParse(template)
|
const ast = baseParse(template)
|
||||||
const srcsetTransform = options
|
const srcsetTransform = options
|
||||||
|
@ -29,9 +29,9 @@ function compileWithSrcset(
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
nodeTransforms: [srcsetTransform, transformElement],
|
nodeTransforms: [srcsetTransform, transformElement],
|
||||||
directiveTransforms: {
|
directiveTransforms: {
|
||||||
bind: transformBind
|
bind: transformBind,
|
||||||
},
|
},
|
||||||
...transformOptions
|
...transformOptions,
|
||||||
})
|
})
|
||||||
return generate(ast, { mode: 'module' })
|
return generate(ast, { mode: 'module' })
|
||||||
}
|
}
|
||||||
|
@ -59,16 +59,16 @@ describe('compiler sfc: transform srcset', () => {
|
||||||
test('transform srcset w/ base', () => {
|
test('transform srcset w/ base', () => {
|
||||||
expect(
|
expect(
|
||||||
compileWithSrcset(src, {
|
compileWithSrcset(src, {
|
||||||
base: '/foo'
|
base: '/foo',
|
||||||
}).code
|
}).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
test('transform srcset w/ includeAbsolute: true', () => {
|
test('transform srcset w/ includeAbsolute: true', () => {
|
||||||
expect(
|
expect(
|
||||||
compileWithSrcset(src, {
|
compileWithSrcset(src, {
|
||||||
includeAbsolute: true
|
includeAbsolute: true,
|
||||||
}).code
|
}).code,
|
||||||
).toMatchSnapshot()
|
).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -76,12 +76,12 @@ describe('compiler sfc: transform srcset', () => {
|
||||||
const code = compileWithSrcset(
|
const code = compileWithSrcset(
|
||||||
`<div>${src}</div>`,
|
`<div>${src}</div>`,
|
||||||
{
|
{
|
||||||
includeAbsolute: true
|
includeAbsolute: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
hoistStatic: true,
|
hoistStatic: true,
|
||||||
transformHoist: stringifyStatic
|
transformHoist: stringifyStatic,
|
||||||
}
|
},
|
||||||
).code
|
).code
|
||||||
expect(code).toMatch(`_createStaticVNode`)
|
expect(code).toMatch(`_createStaticVNode`)
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
|
@ -94,7 +94,7 @@ describe('compiler sfc: transform srcset', () => {
|
||||||
<img srcset="@/logo.png 1x, ./logo.png 2x"/>
|
<img srcset="@/logo.png 1x, ./logo.png 2x"/>
|
||||||
`,
|
`,
|
||||||
{ base: '/foo/' },
|
{ base: '/foo/' },
|
||||||
{ hoistStatic: true }
|
{ hoistStatic: true },
|
||||||
).code
|
).code
|
||||||
expect(code).toMatchSnapshot()
|
expect(code).toMatchSnapshot()
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import {
|
import {
|
||||||
isRelativeUrl,
|
isDataUrl,
|
||||||
isExternalUrl,
|
isExternalUrl,
|
||||||
isDataUrl
|
isRelativeUrl,
|
||||||
} from '../src/template/templateUtils'
|
} from '../src/template/templateUtils'
|
||||||
|
|
||||||
describe('compiler sfc:templateUtils isRelativeUrl', () => {
|
describe('compiler sfc:templateUtils isRelativeUrl', () => {
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import {
|
import {
|
||||||
parse,
|
type SFCParseOptions,
|
||||||
SFCScriptCompileOptions,
|
type SFCScriptCompileOptions,
|
||||||
compileScript,
|
compileScript,
|
||||||
SFCParseOptions
|
parse,
|
||||||
} from '../src'
|
} from '../src'
|
||||||
import { parse as babelParse } from '@babel/parser'
|
import { parse as babelParse } from '@babel/parser'
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@ export const mockId = 'xxxxxxxx'
|
||||||
export function compileSFCScript(
|
export function compileSFCScript(
|
||||||
src: string,
|
src: string,
|
||||||
options?: Partial<SFCScriptCompileOptions>,
|
options?: Partial<SFCScriptCompileOptions>,
|
||||||
parseOptions?: SFCParseOptions
|
parseOptions?: SFCParseOptions,
|
||||||
) {
|
) {
|
||||||
const { descriptor, errors } = parse(src, parseOptions)
|
const { descriptor, errors } = parse(src, parseOptions)
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
|
@ -19,7 +19,7 @@ export function compileSFCScript(
|
||||||
}
|
}
|
||||||
return compileScript(descriptor, {
|
return compileScript(descriptor, {
|
||||||
...options,
|
...options,
|
||||||
id: mockId
|
id: mockId,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,8 +30,8 @@ export function assertCode(code: string) {
|
||||||
sourceType: 'module',
|
sourceType: 'module',
|
||||||
plugins: [
|
plugins: [
|
||||||
'typescript',
|
'typescript',
|
||||||
['importAttributes', { deprecatedAssertSyntax: true }]
|
['importAttributes', { deprecatedAssertSyntax: true }],
|
||||||
]
|
],
|
||||||
})
|
})
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
console.log(code)
|
console.log(code)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { LRUCache } from 'lru-cache'
|
import { LRUCache } from 'lru-cache'
|
||||||
|
|
||||||
export function createCache<T extends {}>(
|
export function createCache<T extends {}>(
|
||||||
max = 500
|
max = 500,
|
||||||
): Map<string, T> | LRUCache<string, T> {
|
): Map<string, T> | LRUCache<string, T> {
|
||||||
if (__GLOBAL__ || __ESM_BROWSER__) {
|
if (__GLOBAL__ || __ESM_BROWSER__) {
|
||||||
return new Map<string, T>()
|
return new Map<string, T>()
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue