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 NodeGlobals = ['module', 'require']
|
||||
|
||||
const banConstEnum = {
|
||||
selector: 'TSEnumDeclaration[const=true]',
|
||||
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 = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
sourceType: 'module'
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['jest'],
|
||||
plugins: ['jest', 'import', '@typescript-eslint'],
|
||||
rules: {
|
||||
'no-debugger': 'error',
|
||||
// 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
|
||||
// still generates verbose helpers, so spread assignment is also prohiboted
|
||||
'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: [
|
||||
// tests, no restrictions (runs in Node / jest with jsdom)
|
||||
|
@ -43,54 +61,66 @@ module.exports = {
|
|||
'no-restricted-globals': 'off',
|
||||
'no-restricted-syntax': 'off',
|
||||
'jest/no-disabled-tests': 'error',
|
||||
'jest/no-focused-tests': 'error'
|
||||
}
|
||||
'jest/no-focused-tests': 'error',
|
||||
},
|
||||
},
|
||||
// shared, may be used in any env
|
||||
{
|
||||
files: ['packages/shared/**'],
|
||||
files: ['packages/shared/**', '.eslintrc.cjs'],
|
||||
rules: {
|
||||
'no-restricted-globals': 'off'
|
||||
}
|
||||
'no-restricted-globals': 'off',
|
||||
},
|
||||
},
|
||||
// Packages targeting DOM
|
||||
{
|
||||
files: ['packages/{vue,vue-compat,runtime-dom}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals]
|
||||
}
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
},
|
||||
},
|
||||
// Packages targeting Node
|
||||
{
|
||||
files: ['packages/{compiler-sfc,compiler-ssr,server-renderer}/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...DOMGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum]
|
||||
}
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
},
|
||||
},
|
||||
// Private package, browser only + no syntax restrictions
|
||||
{
|
||||
files: ['packages/template-explorer/**', 'packages/sfc-playground/**'],
|
||||
rules: {
|
||||
'no-restricted-globals': ['error', ...NodeGlobals],
|
||||
'no-restricted-syntax': ['error', banConstEnum]
|
||||
}
|
||||
'no-restricted-syntax': ['error', banConstEnum],
|
||||
},
|
||||
},
|
||||
// JavaScript files
|
||||
{
|
||||
files: ['*.js', '*.cjs'],
|
||||
rules: {
|
||||
// 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
|
||||
{
|
||||
files: ['scripts/**', '*.{js,ts}', 'packages/**/index.js'],
|
||||
files: [
|
||||
'scripts/**',
|
||||
'./*.{js,ts}',
|
||||
'packages/*/*.js',
|
||||
'packages/vue/*/*.js',
|
||||
],
|
||||
rules: {
|
||||
'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: [
|
||||
{
|
||||
depTypeList: ['peerDependencies'],
|
||||
enabled: false
|
||||
enabled: false,
|
||||
},
|
||||
{
|
||||
groupName: 'test',
|
||||
matchPackageNames: ['vitest', 'jsdom', 'puppeteer'],
|
||||
matchPackagePrefixes: ['@vitest']
|
||||
matchPackagePrefixes: ['@vitest'],
|
||||
},
|
||||
{
|
||||
groupName: 'playground',
|
||||
matchFileNames: [
|
||||
'packages/sfc-playground/package.json',
|
||||
'packages/template-explorer/package.json'
|
||||
]
|
||||
'packages/template-explorer/package.json',
|
||||
],
|
||||
},
|
||||
{
|
||||
groupName: 'compiler',
|
||||
matchPackageNames: ['magic-string'],
|
||||
matchPackagePrefixes: ['@babel', 'postcss']
|
||||
matchPackagePrefixes: ['@babel', 'postcss'],
|
||||
},
|
||||
{
|
||||
groupName: 'build',
|
||||
matchPackageNames: ['vite', 'terser'],
|
||||
matchPackagePrefixes: ['rollup', 'esbuild', '@rollup', '@vitejs']
|
||||
matchPackagePrefixes: ['rollup', 'esbuild', '@rollup', '@vitejs'],
|
||||
},
|
||||
{
|
||||
groupName: 'lint',
|
||||
matchPackageNames: ['simple-git-hooks', 'lint-staged'],
|
||||
matchPackagePrefixes: ['@typescript-eslint', 'eslint', 'prettier']
|
||||
}
|
||||
matchPackagePrefixes: ['@typescript-eslint', 'eslint', 'prettier'],
|
||||
},
|
||||
],
|
||||
ignoreDeps: [
|
||||
'vue',
|
||||
|
@ -45,6 +45,6 @@
|
|||
'typescript',
|
||||
|
||||
// ESM only
|
||||
'estree-walker'
|
||||
]
|
||||
'estree-walker',
|
||||
],
|
||||
}
|
||||
|
|
|
@ -1 +1,4 @@
|
|||
dist
|
||||
*.md
|
||||
*.html
|
||||
pnpm-lock.yaml
|
||||
|
|
10
.prettierrc
10
.prettierrc
|
@ -1,5 +1,5 @@
|
|||
semi: false
|
||||
singleQuote: true
|
||||
printWidth: 80
|
||||
trailingComma: 'none'
|
||||
arrowParens: 'avoid'
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"arrowParens": "avoid"
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
"console": "integratedTerminal",
|
||||
"sourceMaps": true,
|
||||
"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": "node scripts/build.js runtime-dom runtime-core reactivity shared -f esm-bundler",
|
||||
"check": "tsc --incremental --noEmit",
|
||||
"lint": "eslint --cache --ext .ts packages/*/{src,__tests__}/**.ts",
|
||||
"format": "prettier --write --cache \"**/*.[tj]s?(x)\"",
|
||||
"format-check": "prettier --check --cache \"**/*.[tj]s?(x)\"",
|
||||
"lint": "eslint --cache --ext .js,.ts,.tsx .",
|
||||
"format": "prettier --write --cache .",
|
||||
"format-check": "prettier --check --cache .",
|
||||
"test": "vitest",
|
||||
"test-unit": "vitest -c vitest.unit.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/node": "^20.10.5",
|
||||
"@types/semver": "^7.5.5",
|
||||
"@typescript-eslint/eslint-plugin": "^6.16.0",
|
||||
"@typescript-eslint/parser": "^6.15.0",
|
||||
"@vitest/coverage-istanbul": "^1.1.0",
|
||||
"@vue/consolidate": "0.17.3",
|
||||
|
@ -81,6 +82,7 @@
|
|||
"esbuild-plugin-polyfill-node": "^0.3.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-define-config": "^1.24.1",
|
||||
"eslint-plugin-import": "npm:eslint-plugin-i@^2.29.1",
|
||||
"eslint-plugin-jest": "^27.6.0",
|
||||
"estree-walker": "^2.0.2",
|
||||
"execa": "^8.0.1",
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
import {
|
||||
locStub,
|
||||
generate,
|
||||
ConstantTypes,
|
||||
type DirectiveArguments,
|
||||
type ForCodegenNode,
|
||||
type IfConditionalExpression,
|
||||
NodeTypes,
|
||||
RootNode,
|
||||
createSimpleExpression,
|
||||
type RootNode,
|
||||
type VNodeCall,
|
||||
createArrayExpression,
|
||||
createAssignmentExpression,
|
||||
createBlockStatement,
|
||||
createCacheExpression,
|
||||
createCallExpression,
|
||||
createCompoundExpression,
|
||||
createConditionalExpression,
|
||||
createIfStatement,
|
||||
createInterpolation,
|
||||
createObjectExpression,
|
||||
createObjectProperty,
|
||||
createArrayExpression,
|
||||
createCompoundExpression,
|
||||
createInterpolation,
|
||||
createCallExpression,
|
||||
createConditionalExpression,
|
||||
ForCodegenNode,
|
||||
createCacheExpression,
|
||||
createSimpleExpression,
|
||||
createTemplateLiteral,
|
||||
createBlockStatement,
|
||||
createIfStatement,
|
||||
createAssignmentExpression,
|
||||
IfConditionalExpression,
|
||||
createVNodeCall,
|
||||
VNodeCall,
|
||||
DirectiveArguments,
|
||||
ConstantTypes
|
||||
generate,
|
||||
locStub,
|
||||
} from '../src'
|
||||
import {
|
||||
CREATE_VNODE,
|
||||
TO_DISPLAY_STRING,
|
||||
RESOLVE_DIRECTIVE,
|
||||
helperNameMap,
|
||||
RESOLVE_COMPONENT,
|
||||
CREATE_COMMENT,
|
||||
CREATE_ELEMENT_VNODE,
|
||||
CREATE_VNODE,
|
||||
FRAGMENT,
|
||||
RENDER_LIST,
|
||||
CREATE_ELEMENT_VNODE
|
||||
RESOLVE_COMPONENT,
|
||||
RESOLVE_DIRECTIVE,
|
||||
TO_DISPLAY_STRING,
|
||||
helperNameMap,
|
||||
} from '../src/runtimeHelpers'
|
||||
import { createElementWithCodegen, genFlagText } from './testUtils'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
|
@ -51,59 +51,59 @@ function createRoot(options: Partial<RootNode> = {}): RootNode {
|
|||
temps: 0,
|
||||
codegenNode: createSimpleExpression(`null`, false),
|
||||
loc: locStub,
|
||||
...options
|
||||
...options,
|
||||
}
|
||||
}
|
||||
|
||||
describe('compiler: codegen', () => {
|
||||
test('module mode preamble', () => {
|
||||
const root = createRoot({
|
||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
|
||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),
|
||||
})
|
||||
const { code } = generate(root, { mode: 'module' })
|
||||
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()
|
||||
})
|
||||
|
||||
test('module mode preamble w/ optimizeImports: true', () => {
|
||||
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 })
|
||||
expect(code).toMatch(
|
||||
`import { ${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} } from "vue"`
|
||||
`import { ${helperNameMap[CREATE_VNODE]}, ${helperNameMap[RESOLVE_DIRECTIVE]} } from "vue"`,
|
||||
)
|
||||
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()
|
||||
})
|
||||
|
||||
test('function mode preamble', () => {
|
||||
const root = createRoot({
|
||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
|
||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),
|
||||
})
|
||||
const { code } = generate(root, { mode: 'function' })
|
||||
expect(code).toMatch(`const _Vue = Vue`)
|
||||
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()
|
||||
})
|
||||
|
||||
test('function mode preamble w/ prefixIdentifiers: true', () => {
|
||||
const root = createRoot({
|
||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE])
|
||||
helpers: new Set([CREATE_VNODE, RESOLVE_DIRECTIVE]),
|
||||
})
|
||||
const { code } = generate(root, {
|
||||
mode: 'function',
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(code).not.toMatch(`const _Vue = Vue`)
|
||||
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()
|
||||
})
|
||||
|
@ -112,27 +112,27 @@ describe('compiler: codegen', () => {
|
|||
const root = createRoot({
|
||||
components: [`Foo`, `bar-baz`, `barbaz`, `Qux__self`],
|
||||
directives: [`my_dir_0`, `my_dir_1`],
|
||||
temps: 3
|
||||
temps: 3,
|
||||
})
|
||||
const { code } = generate(root, { mode: 'function' })
|
||||
expect(code).toMatch(
|
||||
`const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n`
|
||||
`const _component_Foo = _${helperNameMap[RESOLVE_COMPONENT]}("Foo")\n`,
|
||||
)
|
||||
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(
|
||||
`const _component_barbaz = _${helperNameMap[RESOLVE_COMPONENT]}("barbaz")\n`
|
||||
`const _component_barbaz = _${helperNameMap[RESOLVE_COMPONENT]}("barbaz")\n`,
|
||||
)
|
||||
// implicit self reference from SFC filename
|
||||
expect(code).toMatch(
|
||||
`const _component_Qux = _${helperNameMap[RESOLVE_COMPONENT]}("Qux", true)\n`
|
||||
`const _component_Qux = _${helperNameMap[RESOLVE_COMPONENT]}("Qux", true)\n`,
|
||||
)
|
||||
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(
|
||||
`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).toMatchSnapshot()
|
||||
|
@ -146,12 +146,12 @@ describe('compiler: codegen', () => {
|
|||
[
|
||||
createObjectProperty(
|
||||
createSimpleExpression(`id`, true, locStub),
|
||||
createSimpleExpression(`foo`, true, locStub)
|
||||
)
|
||||
createSimpleExpression(`foo`, true, locStub),
|
||||
),
|
||||
],
|
||||
locStub
|
||||
)
|
||||
]
|
||||
locStub,
|
||||
),
|
||||
],
|
||||
})
|
||||
const { code } = generate(root)
|
||||
expect(code).toMatch(`const _hoisted_1 = hello`)
|
||||
|
@ -161,7 +161,7 @@ describe('compiler: codegen', () => {
|
|||
|
||||
test('temps', () => {
|
||||
const root = createRoot({
|
||||
temps: 3
|
||||
temps: 3,
|
||||
})
|
||||
const { code } = generate(root)
|
||||
expect(code).toMatch(`let _temp0, _temp1, _temp2`)
|
||||
|
@ -174,9 +174,9 @@ describe('compiler: codegen', () => {
|
|||
codegenNode: {
|
||||
type: NodeTypes.TEXT,
|
||||
content: 'hello',
|
||||
loc: locStub
|
||||
}
|
||||
})
|
||||
loc: locStub,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(`return "hello"`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -185,8 +185,8 @@ describe('compiler: codegen', () => {
|
|||
test('interpolation', () => {
|
||||
const { code } = generate(
|
||||
createRoot({
|
||||
codegenNode: createInterpolation(`hello`, locStub)
|
||||
})
|
||||
codegenNode: createInterpolation(`hello`, locStub),
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(`return _${helperNameMap[TO_DISPLAY_STRING]}(hello)`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -198,9 +198,9 @@ describe('compiler: codegen', () => {
|
|||
codegenNode: {
|
||||
type: NodeTypes.COMMENT,
|
||||
content: 'foo',
|
||||
loc: locStub
|
||||
}
|
||||
})
|
||||
loc: locStub,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(`return _${helperNameMap[CREATE_COMMENT]}("foo")`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -216,15 +216,15 @@ describe('compiler: codegen', () => {
|
|||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
loc: locStub,
|
||||
content: createSimpleExpression(`bar`, false, locStub)
|
||||
content: createSimpleExpression(`bar`, false, locStub),
|
||||
},
|
||||
// nested compound
|
||||
createCompoundExpression([` + `, `nested`])
|
||||
])
|
||||
})
|
||||
createCompoundExpression([` + `, `nested`]),
|
||||
]),
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(
|
||||
`return _ctx.foo + _${helperNameMap[TO_DISPLAY_STRING]}(bar) + nested`
|
||||
`return _ctx.foo + _${helperNameMap[TO_DISPLAY_STRING]}(bar) + nested`,
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -239,10 +239,10 @@ describe('compiler: codegen', () => {
|
|||
codegenNode: createConditionalExpression(
|
||||
createSimpleExpression('foo', false),
|
||||
createSimpleExpression('bar', false),
|
||||
createSimpleExpression('baz', false)
|
||||
) as IfConditionalExpression
|
||||
}
|
||||
})
|
||||
createSimpleExpression('baz', false),
|
||||
) as IfConditionalExpression,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(/return foo\s+\? bar\s+: baz/)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -270,10 +270,10 @@ describe('compiler: codegen', () => {
|
|||
patchFlag: '1',
|
||||
dynamicProps: undefined,
|
||||
directives: undefined,
|
||||
loc: locStub
|
||||
} as ForCodegenNode
|
||||
}
|
||||
})
|
||||
loc: locStub,
|
||||
} as ForCodegenNode,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(`openBlock(true)`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -289,7 +289,7 @@ describe('compiler: codegen', () => {
|
|||
'1 + 2',
|
||||
false,
|
||||
locStub,
|
||||
ConstantTypes.CAN_STRINGIFY
|
||||
ConstantTypes.CAN_STRINGIFY,
|
||||
),
|
||||
valueAlias: undefined,
|
||||
keyAlias: undefined,
|
||||
|
@ -306,10 +306,10 @@ describe('compiler: codegen', () => {
|
|||
patchFlag: genFlagText(PatchFlags.STABLE_FRAGMENT),
|
||||
dynamicProps: undefined,
|
||||
directives: undefined,
|
||||
loc: locStub
|
||||
} as ForCodegenNode
|
||||
}
|
||||
})
|
||||
loc: locStub,
|
||||
} as ForCodegenNode,
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(`openBlock()`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -326,11 +326,11 @@ describe('compiler: codegen', () => {
|
|||
[
|
||||
createObjectProperty(
|
||||
createSimpleExpression(`id`, true, locStub),
|
||||
createSimpleExpression(`foo`, true, locStub)
|
||||
createSimpleExpression(`foo`, true, locStub),
|
||||
),
|
||||
createObjectProperty(
|
||||
createSimpleExpression(`prop`, false, locStub),
|
||||
createSimpleExpression(`bar`, false, locStub)
|
||||
createSimpleExpression(`bar`, false, locStub),
|
||||
),
|
||||
// compound expression as computed key
|
||||
createObjectProperty(
|
||||
|
@ -339,13 +339,13 @@ describe('compiler: codegen', () => {
|
|||
loc: locStub,
|
||||
children: [
|
||||
`foo + `,
|
||||
createSimpleExpression(`bar`, false, locStub)
|
||||
]
|
||||
createSimpleExpression(`bar`, false, locStub),
|
||||
],
|
||||
},
|
||||
createSimpleExpression(`bar`, false, locStub)
|
||||
)
|
||||
createSimpleExpression(`bar`, false, locStub),
|
||||
),
|
||||
],
|
||||
locStub
|
||||
locStub,
|
||||
),
|
||||
// ChildNode[]
|
||||
[
|
||||
|
@ -356,17 +356,17 @@ describe('compiler: codegen', () => {
|
|||
createObjectProperty(
|
||||
// should quote the key!
|
||||
createSimpleExpression(`some-key`, true, locStub),
|
||||
createSimpleExpression(`foo`, true, locStub)
|
||||
)
|
||||
createSimpleExpression(`foo`, true, locStub),
|
||||
),
|
||||
],
|
||||
locStub
|
||||
)
|
||||
)
|
||||
locStub,
|
||||
),
|
||||
),
|
||||
],
|
||||
// flag
|
||||
PatchFlags.FULL_PROPS + ''
|
||||
)
|
||||
})
|
||||
PatchFlags.FULL_PROPS + '',
|
||||
),
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(`
|
||||
return _${helperNameMap[CREATE_ELEMENT_VNODE]}("div", {
|
||||
|
@ -384,9 +384,9 @@ describe('compiler: codegen', () => {
|
|||
createRoot({
|
||||
codegenNode: createArrayExpression([
|
||||
createSimpleExpression(`foo`, false),
|
||||
createCallExpression(`bar`, [`baz`])
|
||||
])
|
||||
})
|
||||
createCallExpression(`bar`, [`baz`]),
|
||||
]),
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(`return [
|
||||
foo,
|
||||
|
@ -404,17 +404,17 @@ describe('compiler: codegen', () => {
|
|||
createConditionalExpression(
|
||||
createSimpleExpression(`orNot`, false),
|
||||
createCallExpression(`bar`),
|
||||
createCallExpression(`baz`)
|
||||
)
|
||||
)
|
||||
})
|
||||
createCallExpression(`baz`),
|
||||
),
|
||||
),
|
||||
}),
|
||||
)
|
||||
expect(code).toMatch(
|
||||
`return ok
|
||||
? foo()
|
||||
: orNot
|
||||
? bar()
|
||||
: baz()`
|
||||
: baz()`,
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -425,13 +425,13 @@ describe('compiler: codegen', () => {
|
|||
cached: 1,
|
||||
codegenNode: createCacheExpression(
|
||||
1,
|
||||
createSimpleExpression(`foo`, false)
|
||||
)
|
||||
createSimpleExpression(`foo`, false),
|
||||
),
|
||||
}),
|
||||
{
|
||||
mode: 'module',
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
expect(code).toMatch(`_cache[1] || (_cache[1] = foo)`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -444,13 +444,13 @@ describe('compiler: codegen', () => {
|
|||
codegenNode: createCacheExpression(
|
||||
1,
|
||||
createSimpleExpression(`foo`, false),
|
||||
true
|
||||
)
|
||||
true,
|
||||
),
|
||||
}),
|
||||
{
|
||||
mode: 'module',
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
expect(code).toMatch(
|
||||
`
|
||||
|
@ -460,7 +460,7 @@ describe('compiler: codegen', () => {
|
|||
_setBlockTracking(1),
|
||||
_cache[1]
|
||||
)
|
||||
`.trim()
|
||||
`.trim(),
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -472,11 +472,11 @@ describe('compiler: codegen', () => {
|
|||
createTemplateLiteral([
|
||||
`foo`,
|
||||
createCallExpression(`_renderAttr`, ['id', 'foo']),
|
||||
`bar`
|
||||
])
|
||||
])
|
||||
`bar`,
|
||||
]),
|
||||
]),
|
||||
}),
|
||||
{ ssr: true, mode: 'module' }
|
||||
{ ssr: true, mode: 'module' },
|
||||
)
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
"
|
||||
|
@ -493,11 +493,11 @@ describe('compiler: codegen', () => {
|
|||
codegenNode: createBlockStatement([
|
||||
createIfStatement(
|
||||
createSimpleExpression('foo', false),
|
||||
createBlockStatement([createCallExpression(`ok`)])
|
||||
)
|
||||
])
|
||||
createBlockStatement([createCallExpression(`ok`)]),
|
||||
),
|
||||
]),
|
||||
}),
|
||||
{ ssr: true, mode: 'module' }
|
||||
{ ssr: true, mode: 'module' },
|
||||
)
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
"
|
||||
|
@ -516,11 +516,11 @@ describe('compiler: codegen', () => {
|
|||
createIfStatement(
|
||||
createSimpleExpression('foo', false),
|
||||
createBlockStatement([createCallExpression(`foo`)]),
|
||||
createBlockStatement([createCallExpression('bar')])
|
||||
)
|
||||
])
|
||||
createBlockStatement([createCallExpression('bar')]),
|
||||
),
|
||||
]),
|
||||
}),
|
||||
{ ssr: true, mode: 'module' }
|
||||
{ ssr: true, mode: 'module' },
|
||||
)
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
"
|
||||
|
@ -543,12 +543,12 @@ describe('compiler: codegen', () => {
|
|||
createBlockStatement([createCallExpression(`foo`)]),
|
||||
createIfStatement(
|
||||
createSimpleExpression('bar', false),
|
||||
createBlockStatement([createCallExpression(`bar`)])
|
||||
)
|
||||
)
|
||||
])
|
||||
createBlockStatement([createCallExpression(`bar`)]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
}),
|
||||
{ ssr: true, mode: 'module' }
|
||||
{ ssr: true, mode: 'module' },
|
||||
)
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
"
|
||||
|
@ -572,12 +572,12 @@ describe('compiler: codegen', () => {
|
|||
createIfStatement(
|
||||
createSimpleExpression('bar', false),
|
||||
createBlockStatement([createCallExpression(`bar`)]),
|
||||
createBlockStatement([createCallExpression('baz')])
|
||||
)
|
||||
)
|
||||
])
|
||||
createBlockStatement([createCallExpression('baz')]),
|
||||
),
|
||||
),
|
||||
]),
|
||||
}),
|
||||
{ ssr: true, mode: 'module' }
|
||||
{ ssr: true, mode: 'module' },
|
||||
)
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
"
|
||||
|
@ -599,9 +599,9 @@ describe('compiler: codegen', () => {
|
|||
createRoot({
|
||||
codegenNode: createAssignmentExpression(
|
||||
createSimpleExpression(`foo`, false),
|
||||
createSimpleExpression(`bar`, false)
|
||||
)
|
||||
})
|
||||
createSimpleExpression(`bar`, false),
|
||||
),
|
||||
}),
|
||||
)
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
"
|
||||
|
@ -617,17 +617,17 @@ describe('compiler: codegen', () => {
|
|||
function genCode(node: VNodeCall) {
|
||||
return generate(
|
||||
createRoot({
|
||||
codegenNode: node
|
||||
})
|
||||
codegenNode: node,
|
||||
}),
|
||||
).code.match(/with \(_ctx\) \{\s+([^]+)\s+\}\s+\}$/)![1]
|
||||
}
|
||||
|
||||
const mockProps = createObjectExpression([
|
||||
createObjectProperty(`foo`, createSimpleExpression(`bar`, true))
|
||||
createObjectProperty(`foo`, createSimpleExpression(`bar`, true)),
|
||||
])
|
||||
const mockChildren = createCompoundExpression(['children'])
|
||||
const mockDirs = createArrayExpression([
|
||||
createArrayExpression([`foo`, createSimpleExpression(`bar`, false)])
|
||||
createArrayExpression([`foo`, createSimpleExpression(`bar`, false)]),
|
||||
]) as DirectiveArguments
|
||||
|
||||
test('tag only', () => {
|
||||
|
@ -684,9 +684,9 @@ describe('compiler: codegen', () => {
|
|||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
true
|
||||
)
|
||||
)
|
||||
true,
|
||||
),
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"return (_openBlock(), _createElementBlock("div", { foo: "bar" }, children))
|
||||
"
|
||||
|
@ -705,9 +705,9 @@ describe('compiler: codegen', () => {
|
|||
undefined,
|
||||
undefined,
|
||||
true,
|
||||
true
|
||||
)
|
||||
)
|
||||
true,
|
||||
),
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"return (_openBlock(true), _createElementBlock("div", { foo: "bar" }, children))
|
||||
"
|
||||
|
@ -724,9 +724,9 @@ describe('compiler: codegen', () => {
|
|||
mockChildren,
|
||||
undefined,
|
||||
undefined,
|
||||
mockDirs
|
||||
)
|
||||
)
|
||||
mockDirs,
|
||||
),
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"return _withDirectives(_createElementVNode("div", { foo: "bar" }, children), [
|
||||
[foo, bar]
|
||||
|
@ -746,9 +746,9 @@ describe('compiler: codegen', () => {
|
|||
undefined,
|
||||
undefined,
|
||||
mockDirs,
|
||||
true
|
||||
)
|
||||
)
|
||||
true,
|
||||
),
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"return _withDirectives((_openBlock(), _createElementBlock("div", { foo: "bar" }, children)), [
|
||||
[foo, bar]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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', () => {
|
||||
const source = `
|
||||
|
@ -20,7 +20,7 @@ describe('compiler: integration tests', () => {
|
|||
function getPositionInCode(
|
||||
code: string,
|
||||
token: string,
|
||||
expectName: string | boolean = false
|
||||
expectName: string | boolean = false,
|
||||
): Pos {
|
||||
const generatedOffset = code.indexOf(token)
|
||||
let line = 1
|
||||
|
@ -36,7 +36,7 @@ describe('compiler: integration tests', () => {
|
|||
column:
|
||||
lastNewLinePos === -1
|
||||
? generatedOffset
|
||||
: generatedOffset - lastNewLinePos - 1
|
||||
: generatedOffset - lastNewLinePos - 1,
|
||||
}
|
||||
if (expectName) {
|
||||
res.name = typeof expectName === 'string' ? expectName : token
|
||||
|
@ -47,7 +47,7 @@ describe('compiler: integration tests', () => {
|
|||
test('function mode', () => {
|
||||
const { code, map } = compile(source, {
|
||||
sourceMap: true,
|
||||
filename: `foo.vue`
|
||||
filename: `foo.vue`,
|
||||
})
|
||||
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -57,55 +57,55 @@ describe('compiler: integration tests', () => {
|
|||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `id`)),
|
||||
).toMatchObject(getPositionInCode(source, `id`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`)),
|
||||
).toMatchObject(getPositionInCode(source, `"foo"`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `class:`)),
|
||||
).toMatchObject(getPositionInCode(source, `class=`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `bar`)),
|
||||
).toMatchObject(getPositionInCode(source, `bar`))
|
||||
|
||||
// without prefixIdentifiers: true, identifiers inside compound expressions
|
||||
// are mapped to closest parent expression.
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `baz`)),
|
||||
).toMatchObject(getPositionInCode(source, `bar`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `world`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `world`)),
|
||||
).toMatchObject(getPositionInCode(source, `world`))
|
||||
|
||||
// without prefixIdentifiers: true, identifiers inside compound expressions
|
||||
// are mapped to closest parent expression.
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`)),
|
||||
).toMatchObject(getPositionInCode(source, `world`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `ok`)),
|
||||
).toMatchObject(getPositionInCode(source, `ok`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `list`)),
|
||||
).toMatchObject(getPositionInCode(source, `list`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value`)),
|
||||
).toMatchObject(getPositionInCode(source, `value`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `index`)),
|
||||
).toMatchObject(getPositionInCode(source, `index`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`)),
|
||||
).toMatchObject(getPositionInCode(source, `value + index`))
|
||||
})
|
||||
|
||||
|
@ -113,7 +113,7 @@ describe('compiler: integration tests', () => {
|
|||
const { code, map } = compile(source, {
|
||||
sourceMap: true,
|
||||
filename: `foo.vue`,
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -123,64 +123,66 @@ describe('compiler: integration tests', () => {
|
|||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `id`)),
|
||||
).toMatchObject(getPositionInCode(source, `id`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`)),
|
||||
).toMatchObject(getPositionInCode(source, `"foo"`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `class:`)),
|
||||
).toMatchObject(getPositionInCode(source, `class=`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `bar`)),
|
||||
).toMatchObject(getPositionInCode(source, `bar`))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`)),
|
||||
).toMatchObject(getPositionInCode(source, `bar`, true))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `baz`)),
|
||||
).toMatchObject(getPositionInCode(source, `baz`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `world`, true)),
|
||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||
expect(
|
||||
consumer.originalPositionFor(
|
||||
getPositionInCode(code, `_ctx.world`, `world`)
|
||||
)
|
||||
getPositionInCode(code, `_ctx.world`, `world`),
|
||||
),
|
||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`)),
|
||||
).toMatchObject(getPositionInCode(source, `burn()`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `ok`)),
|
||||
).toMatchObject(getPositionInCode(source, `ok`))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`)),
|
||||
).toMatchObject(getPositionInCode(source, `ok`, true))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `list`)),
|
||||
).toMatchObject(getPositionInCode(source, `list`))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
|
||||
consumer.originalPositionFor(
|
||||
getPositionInCode(code, `_ctx.list`, `list`),
|
||||
),
|
||||
).toMatchObject(getPositionInCode(source, `list`, true))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value`)),
|
||||
).toMatchObject(getPositionInCode(source, `value`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `index`)),
|
||||
).toMatchObject(getPositionInCode(source, `index`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`)),
|
||||
).toMatchObject(getPositionInCode(source, `value + index`))
|
||||
})
|
||||
|
||||
|
@ -188,7 +190,7 @@ describe('compiler: integration tests', () => {
|
|||
const { code, map } = compile(source, {
|
||||
mode: 'module',
|
||||
sourceMap: true,
|
||||
filename: `foo.vue`
|
||||
filename: `foo.vue`,
|
||||
})
|
||||
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -198,64 +200,66 @@ describe('compiler: integration tests', () => {
|
|||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `id`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `id`)),
|
||||
).toMatchObject(getPositionInCode(source, `id`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `"foo"`)),
|
||||
).toMatchObject(getPositionInCode(source, `"foo"`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `class:`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `class:`)),
|
||||
).toMatchObject(getPositionInCode(source, `class=`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `bar`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `bar`)),
|
||||
).toMatchObject(getPositionInCode(source, `bar`))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.bar`, `bar`)),
|
||||
).toMatchObject(getPositionInCode(source, `bar`, true))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `baz`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `baz`)),
|
||||
).toMatchObject(getPositionInCode(source, `baz`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `world`, true))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `world`, true)),
|
||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||
expect(
|
||||
consumer.originalPositionFor(
|
||||
getPositionInCode(code, `_ctx.world`, `world`)
|
||||
)
|
||||
getPositionInCode(code, `_ctx.world`, `world`),
|
||||
),
|
||||
).toMatchObject(getPositionInCode(source, `world`, `world`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `burn()`)),
|
||||
).toMatchObject(getPositionInCode(source, `burn()`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `ok`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `ok`)),
|
||||
).toMatchObject(getPositionInCode(source, `ok`))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.ok`, `ok`)),
|
||||
).toMatchObject(getPositionInCode(source, `ok`, true))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `list`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `list`)),
|
||||
).toMatchObject(getPositionInCode(source, `list`))
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `_ctx.list`, `list`))
|
||||
consumer.originalPositionFor(
|
||||
getPositionInCode(code, `_ctx.list`, `list`),
|
||||
),
|
||||
).toMatchObject(getPositionInCode(source, `list`, true))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value`)),
|
||||
).toMatchObject(getPositionInCode(source, `value`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `index`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `index`)),
|
||||
).toMatchObject(getPositionInCode(source, `index`))
|
||||
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, `value + index`))
|
||||
consumer.originalPositionFor(getPositionInCode(code, `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 { 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 { genFlagText } from './testUtils'
|
||||
|
||||
|
@ -18,7 +18,7 @@ describe('scopeId compiler support', () => {
|
|||
test('should wrap default slot', () => {
|
||||
const { code } = baseCompile(`<Child><div/></Child>`, {
|
||||
mode: 'module',
|
||||
scopeId: 'test'
|
||||
scopeId: 'test',
|
||||
})
|
||||
expect(code).toMatch(`default: _withCtx(() => [`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -33,8 +33,8 @@ describe('scopeId compiler support', () => {
|
|||
`,
|
||||
{
|
||||
mode: 'module',
|
||||
scopeId: 'test'
|
||||
}
|
||||
scopeId: 'test',
|
||||
},
|
||||
)
|
||||
expect(code).toMatch(`foo: _withCtx(({ msg }) => [`)
|
||||
expect(code).toMatch(`bar: _withCtx(() => [`)
|
||||
|
@ -50,8 +50,8 @@ describe('scopeId compiler support', () => {
|
|||
`,
|
||||
{
|
||||
mode: 'module',
|
||||
scopeId: 'test'
|
||||
}
|
||||
scopeId: 'test',
|
||||
},
|
||||
)
|
||||
expect(code).toMatch(/name: "foo",\s+fn: _withCtx\(/)
|
||||
expect(code).toMatch(/name: i,\s+fn: _withCtx\(/)
|
||||
|
@ -64,8 +64,8 @@ describe('scopeId compiler support', () => {
|
|||
{
|
||||
mode: 'module',
|
||||
scopeId: 'test',
|
||||
hoistStatic: true
|
||||
}
|
||||
hoistStatic: true,
|
||||
},
|
||||
)
|
||||
expect(ast.helpers).toContain(PUSH_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 _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(
|
||||
PatchFlags.HOISTED
|
||||
)}))`
|
||||
PatchFlags.HOISTED,
|
||||
)}))`,
|
||||
].forEach(c => expect(code).toMatch(c))
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import {
|
||||
NodeTypes,
|
||||
ElementNode,
|
||||
locStub,
|
||||
Namespaces,
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
VNodeCall
|
||||
Namespaces,
|
||||
NodeTypes,
|
||||
type VNodeCall,
|
||||
locStub,
|
||||
} from '../src'
|
||||
import {
|
||||
isString,
|
||||
PatchFlags,
|
||||
PatchFlagNames,
|
||||
type PatchFlags,
|
||||
type ShapeFlags,
|
||||
isArray,
|
||||
ShapeFlags
|
||||
isString,
|
||||
} from '@vue/shared'
|
||||
|
||||
const leadingBracketRE = /^\[/
|
||||
|
@ -30,16 +30,16 @@ export function createObjectMatcher(obj: Record<string, any>) {
|
|||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: key.replace(bracketsRE, ''),
|
||||
isStatic: !leadingBracketRE.test(key)
|
||||
isStatic: !leadingBracketRE.test(key),
|
||||
},
|
||||
value: isString(obj[key])
|
||||
? {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
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'],
|
||||
children?: VNodeCall['children'],
|
||||
patchFlag?: VNodeCall['patchFlag'],
|
||||
dynamicProps?: VNodeCall['dynamicProps']
|
||||
dynamicProps?: VNodeCall['dynamicProps'],
|
||||
): ElementNode {
|
||||
return {
|
||||
type: NodeTypes.ELEMENT,
|
||||
|
@ -69,15 +69,15 @@ export function createElementWithCodegen(
|
|||
isBlock: false,
|
||||
disableTracking: false,
|
||||
isComponent: false,
|
||||
loc: locStub
|
||||
}
|
||||
loc: locStub,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type Flags = PatchFlags | ShapeFlags
|
||||
export function genFlagText(
|
||||
flag: Flags | Flags[],
|
||||
names: { [k: number]: string } = PatchFlagNames
|
||||
names: { [k: number]: string } = PatchFlagNames,
|
||||
) {
|
||||
if (isArray(flag)) {
|
||||
let f = 0
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import { baseParse } from '../src/parser'
|
||||
import { transform, NodeTransform } from '../src/transform'
|
||||
import { type NodeTransform, transform } from '../src/transform'
|
||||
import {
|
||||
ElementNode,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
DirectiveNode,
|
||||
ExpressionNode,
|
||||
VNodeCall
|
||||
type VNodeCall,
|
||||
} from '../src/ast'
|
||||
import { ErrorCodes, createCompilerError } from '../src/errors'
|
||||
import {
|
||||
TO_DISPLAY_STRING,
|
||||
CREATE_COMMENT,
|
||||
FRAGMENT,
|
||||
RENDER_SLOT,
|
||||
CREATE_COMMENT
|
||||
TO_DISPLAY_STRING,
|
||||
} from '../src/runtimeHelpers'
|
||||
import { transformIf } from '../src/transforms/vIf'
|
||||
import { transformFor } from '../src/transforms/vFor'
|
||||
|
@ -34,7 +34,7 @@ describe('compiler: transform', () => {
|
|||
}
|
||||
|
||||
transform(ast, {
|
||||
nodeTransforms: [plugin]
|
||||
nodeTransforms: [plugin],
|
||||
})
|
||||
|
||||
const div = ast.children[0] as ElementNode
|
||||
|
@ -43,29 +43,29 @@ describe('compiler: transform', () => {
|
|||
ast,
|
||||
{
|
||||
parent: null,
|
||||
currentNode: ast
|
||||
}
|
||||
currentNode: ast,
|
||||
},
|
||||
])
|
||||
expect(calls[1]).toMatchObject([
|
||||
div,
|
||||
{
|
||||
parent: ast,
|
||||
currentNode: div
|
||||
}
|
||||
currentNode: div,
|
||||
},
|
||||
])
|
||||
expect(calls[2]).toMatchObject([
|
||||
div.children[0],
|
||||
{
|
||||
parent: div,
|
||||
currentNode: div.children[0]
|
||||
}
|
||||
currentNode: div.children[0],
|
||||
},
|
||||
])
|
||||
expect(calls[3]).toMatchObject([
|
||||
div.children[1],
|
||||
{
|
||||
parent: div,
|
||||
currentNode: div.children[1]
|
||||
}
|
||||
currentNode: div.children[1],
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
|
@ -81,16 +81,16 @@ describe('compiler: transform', () => {
|
|||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: 'hello',
|
||||
isEmpty: false
|
||||
}
|
||||
]
|
||||
})
|
||||
isEmpty: false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
const spy = vi.fn(plugin)
|
||||
transform(ast, {
|
||||
nodeTransforms: [spy]
|
||||
nodeTransforms: [spy],
|
||||
})
|
||||
|
||||
expect(ast.children.length).toBe(2)
|
||||
|
@ -115,7 +115,7 @@ describe('compiler: transform', () => {
|
|||
}
|
||||
const spy = vi.fn(plugin)
|
||||
transform(ast, {
|
||||
nodeTransforms: [spy]
|
||||
nodeTransforms: [spy],
|
||||
})
|
||||
|
||||
expect(ast.children.length).toBe(2)
|
||||
|
@ -143,7 +143,7 @@ describe('compiler: transform', () => {
|
|||
}
|
||||
const spy = vi.fn(plugin)
|
||||
transform(ast, {
|
||||
nodeTransforms: [spy]
|
||||
nodeTransforms: [spy],
|
||||
})
|
||||
|
||||
expect(ast.children.length).toBe(1)
|
||||
|
@ -170,7 +170,7 @@ describe('compiler: transform', () => {
|
|||
}
|
||||
const spy = vi.fn(plugin)
|
||||
transform(ast, {
|
||||
nodeTransforms: [spy]
|
||||
nodeTransforms: [spy],
|
||||
})
|
||||
|
||||
expect(ast.children.length).toBe(1)
|
||||
|
@ -194,7 +194,7 @@ describe('compiler: transform', () => {
|
|||
}
|
||||
}
|
||||
transform(ast, {
|
||||
nodeTransforms: [mock]
|
||||
nodeTransforms: [mock],
|
||||
})
|
||||
expect(ast.hoists).toMatchObject(hoisted)
|
||||
expect((ast as any).children[0].props[0].exp.content).toBe(`_hoisted_1`)
|
||||
|
@ -211,13 +211,13 @@ describe('compiler: transform', () => {
|
|||
|
||||
transform(ast, {
|
||||
filename: '/the/fileName.vue',
|
||||
nodeTransforms: [plugin]
|
||||
nodeTransforms: [plugin],
|
||||
})
|
||||
|
||||
expect(calls.length).toBe(2)
|
||||
expect(calls[1]).toMatchObject({
|
||||
filename: '/the/fileName.vue',
|
||||
selfName: 'FileName'
|
||||
selfName: 'FileName',
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -226,19 +226,19 @@ describe('compiler: transform', () => {
|
|||
const loc = ast.children[0].loc
|
||||
const plugin: NodeTransform = (node, context) => {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_INVALID_END_TAG, node.loc)
|
||||
createCompilerError(ErrorCodes.X_INVALID_END_TAG, node.loc),
|
||||
)
|
||||
}
|
||||
const spy = vi.fn()
|
||||
transform(ast, {
|
||||
nodeTransforms: [plugin],
|
||||
onError: spy
|
||||
onError: spy,
|
||||
})
|
||||
expect(spy.mock.calls[0]).toMatchObject([
|
||||
{
|
||||
code: ErrorCodes.X_INVALID_END_TAG,
|
||||
loc
|
||||
}
|
||||
loc,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
|
@ -263,8 +263,8 @@ describe('compiler: transform', () => {
|
|||
transformFor,
|
||||
transformText,
|
||||
transformSlotOutlet,
|
||||
transformElement
|
||||
]
|
||||
transformElement,
|
||||
],
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -273,7 +273,7 @@ describe('compiler: transform', () => {
|
|||
tag: VNodeCall['tag'],
|
||||
props?: VNodeCall['props'],
|
||||
children?: VNodeCall['children'],
|
||||
patchFlag?: VNodeCall['patchFlag']
|
||||
patchFlag?: VNodeCall['patchFlag'],
|
||||
) {
|
||||
return {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
|
@ -281,7 +281,7 @@ describe('compiler: transform', () => {
|
|||
tag,
|
||||
props,
|
||||
children,
|
||||
patchFlag
|
||||
patchFlag,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -295,8 +295,8 @@ describe('compiler: transform', () => {
|
|||
expect(ast.codegenNode).toMatchObject({
|
||||
codegenNode: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT
|
||||
}
|
||||
callee: RENDER_SLOT,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -308,14 +308,14 @@ describe('compiler: transform', () => {
|
|||
test('root v-if', () => {
|
||||
const ast = transformWithCodegen(`<div v-if="ok" />`)
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
type: NodeTypes.IF
|
||||
type: NodeTypes.IF,
|
||||
})
|
||||
})
|
||||
|
||||
test('root v-for', () => {
|
||||
const ast = transformWithCodegen(`<div v-for="i in list" />`)
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
type: NodeTypes.FOR
|
||||
type: NodeTypes.FOR,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -323,28 +323,28 @@ describe('compiler: transform', () => {
|
|||
const ast = transformWithCodegen(`<div v-foo/>`)
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION }
|
||||
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION },
|
||||
})
|
||||
})
|
||||
|
||||
test('single text', () => {
|
||||
const ast = transformWithCodegen(`hello`)
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
type: NodeTypes.TEXT
|
||||
type: NodeTypes.TEXT,
|
||||
})
|
||||
})
|
||||
|
||||
test('single interpolation', () => {
|
||||
const ast = transformWithCodegen(`{{ foo }}`)
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
type: NodeTypes.INTERPOLATION
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
})
|
||||
})
|
||||
|
||||
test('single CompoundExpression', () => {
|
||||
const ast = transformWithCodegen(`{{ foo }} bar baz`)
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -356,10 +356,10 @@ describe('compiler: transform', () => {
|
|||
undefined,
|
||||
[
|
||||
{ type: NodeTypes.ELEMENT, tag: `div` },
|
||||
{ type: NodeTypes.ELEMENT, tag: `div` }
|
||||
{ type: NodeTypes.ELEMENT, tag: `div` },
|
||||
] as any,
|
||||
genFlagText(PatchFlags.STABLE_FRAGMENT)
|
||||
)
|
||||
genFlagText(PatchFlags.STABLE_FRAGMENT),
|
||||
),
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -372,13 +372,13 @@ describe('compiler: transform', () => {
|
|||
[
|
||||
{ type: NodeTypes.COMMENT },
|
||||
{ type: NodeTypes.ELEMENT, tag: `div` },
|
||||
{ type: NodeTypes.COMMENT }
|
||||
{ type: NodeTypes.COMMENT },
|
||||
] as any,
|
||||
genFlagText([
|
||||
PatchFlags.STABLE_FRAGMENT,
|
||||
PatchFlags.DEV_ROOT_FRAGMENT
|
||||
])
|
||||
)
|
||||
PatchFlags.DEV_ROOT_FRAGMENT,
|
||||
]),
|
||||
),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
import {
|
||||
type CompilerOptions,
|
||||
ConstantTypes,
|
||||
type ElementNode,
|
||||
type ForNode,
|
||||
type IfNode,
|
||||
NodeTypes,
|
||||
type VNodeCall,
|
||||
generate,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
NodeTypes,
|
||||
generate,
|
||||
CompilerOptions,
|
||||
VNodeCall,
|
||||
IfNode,
|
||||
ElementNode,
|
||||
ForNode,
|
||||
ConstantTypes
|
||||
} from '../../src'
|
||||
import {
|
||||
FRAGMENT,
|
||||
NORMALIZE_CLASS,
|
||||
RENDER_LIST,
|
||||
NORMALIZE_CLASS
|
||||
} from '../../src/runtimeHelpers'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
|
@ -31,9 +31,9 @@ const hoistedChildrenArrayMatcher = (startIndex = 1, length = 1) => ({
|
|||
type: NodeTypes.ELEMENT,
|
||||
codegenNode: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_hoisted_${startIndex + i}`
|
||||
}
|
||||
}))
|
||||
content: `_hoisted_${startIndex + i}`,
|
||||
},
|
||||
})),
|
||||
})
|
||||
|
||||
function transformWithHoist(template: string, options: CompilerOptions = {}) {
|
||||
|
@ -45,17 +45,17 @@ function transformWithHoist(template: string, options: CompilerOptions = {}) {
|
|||
transformFor,
|
||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||
transformElement,
|
||||
transformText
|
||||
transformText,
|
||||
],
|
||||
directiveTransforms: {
|
||||
on: transformOn,
|
||||
bind: transformBind
|
||||
bind: transformBind,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
expect(ast.codegenNode).toMatchObject({
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
isBlock: true
|
||||
isBlock: true,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -67,14 +67,14 @@ describe('compiler: hoistStatic transform', () => {
|
|||
const root = transformWithHoist(`<div/>`)
|
||||
expect(root.hoists.length).toBe(0)
|
||||
expect(root.codegenNode).toMatchObject({
|
||||
tag: `"div"`
|
||||
tag: `"div"`,
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('hoist simple element', () => {
|
||||
const root = transformWithHoist(
|
||||
`<div><span class="inline">hello</span></div>`
|
||||
`<div><span class="inline">hello</span></div>`,
|
||||
)
|
||||
expect(root.hoists).toMatchObject([
|
||||
{
|
||||
|
@ -83,15 +83,15 @@ describe('compiler: hoistStatic transform', () => {
|
|||
props: createObjectMatcher({ class: 'inline' }),
|
||||
children: {
|
||||
type: NodeTypes.TEXT,
|
||||
content: `hello`
|
||||
}
|
||||
content: `hello`,
|
||||
},
|
||||
},
|
||||
hoistedChildrenArrayMatcher()
|
||||
hoistedChildrenArrayMatcher(),
|
||||
])
|
||||
expect(root.codegenNode).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: undefined,
|
||||
children: { content: `_hoisted_2` }
|
||||
children: { content: `_hoisted_2` },
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -105,13 +105,13 @@ describe('compiler: hoistStatic transform', () => {
|
|||
props: undefined,
|
||||
children: [
|
||||
{ type: NodeTypes.ELEMENT, tag: `span` },
|
||||
{ type: NodeTypes.ELEMENT, tag: `span` }
|
||||
]
|
||||
{ type: NodeTypes.ELEMENT, tag: `span` },
|
||||
],
|
||||
},
|
||||
hoistedChildrenArrayMatcher()
|
||||
hoistedChildrenArrayMatcher(),
|
||||
])
|
||||
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
||||
content: '_hoisted_2'
|
||||
content: '_hoisted_2',
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -123,12 +123,12 @@ describe('compiler: hoistStatic transform', () => {
|
|||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: undefined,
|
||||
children: [{ type: NodeTypes.COMMENT, content: `comment` }]
|
||||
children: [{ type: NodeTypes.COMMENT, content: `comment` }],
|
||||
},
|
||||
hoistedChildrenArrayMatcher()
|
||||
hoistedChildrenArrayMatcher(),
|
||||
])
|
||||
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
||||
content: `_hoisted_2`
|
||||
content: `_hoisted_2`,
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -138,16 +138,16 @@ describe('compiler: hoistStatic transform', () => {
|
|||
expect(root.hoists).toMatchObject([
|
||||
{
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"span"`
|
||||
tag: `"span"`,
|
||||
},
|
||||
{
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`
|
||||
tag: `"div"`,
|
||||
},
|
||||
hoistedChildrenArrayMatcher(1, 2)
|
||||
hoistedChildrenArrayMatcher(1, 2),
|
||||
])
|
||||
expect((root.codegenNode as VNodeCall).children).toMatchObject({
|
||||
content: '_hoisted_3'
|
||||
content: '_hoisted_3',
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -160,9 +160,9 @@ describe('compiler: hoistStatic transform', () => {
|
|||
type: NodeTypes.ELEMENT,
|
||||
codegenNode: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `_component_Comp`
|
||||
}
|
||||
}
|
||||
tag: `_component_Comp`,
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -177,17 +177,17 @@ describe('compiler: hoistStatic transform', () => {
|
|||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({
|
||||
id: `[foo]`
|
||||
id: `[foo]`,
|
||||
}),
|
||||
children: undefined,
|
||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||
dynamicProps: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_hoisted_1`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -199,14 +199,14 @@ describe('compiler: hoistStatic transform', () => {
|
|||
{
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: 'foo' })
|
||||
props: createObjectMatcher({ key: 'foo' }),
|
||||
},
|
||||
hoistedChildrenArrayMatcher()
|
||||
hoistedChildrenArrayMatcher(),
|
||||
])
|
||||
expect(root.codegenNode).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: undefined,
|
||||
children: { content: `_hoisted_2` }
|
||||
children: { content: `_hoisted_2` },
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -221,10 +221,10 @@ describe('compiler: hoistStatic transform', () => {
|
|||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({
|
||||
key: `[foo]`
|
||||
})
|
||||
}
|
||||
}
|
||||
key: `[foo]`,
|
||||
}),
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -239,12 +239,12 @@ describe('compiler: hoistStatic transform', () => {
|
|||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({
|
||||
ref: `[foo]`
|
||||
ref: `[foo]`,
|
||||
}),
|
||||
children: undefined,
|
||||
patchFlag: genFlagText(PatchFlags.NEED_PATCH)
|
||||
}
|
||||
}
|
||||
patchFlag: genFlagText(PatchFlags.NEED_PATCH),
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -260,22 +260,22 @@ describe('compiler: hoistStatic transform', () => {
|
|||
tag: `"div"`,
|
||||
props: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_hoisted_1`
|
||||
content: `_hoisted_1`,
|
||||
},
|
||||
children: undefined,
|
||||
patchFlag: genFlagText(PatchFlags.NEED_PATCH),
|
||||
directives: {
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
||||
}
|
||||
}
|
||||
}
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('hoist static props for elements with dynamic text children', () => {
|
||||
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.codegenNode as VNodeCall).children).toMatchObject([
|
||||
|
@ -286,9 +286,9 @@ describe('compiler: hoistStatic transform', () => {
|
|||
tag: `"div"`,
|
||||
props: { content: `_hoisted_1` },
|
||||
children: { type: NodeTypes.INTERPOLATION },
|
||||
patchFlag: genFlagText(PatchFlags.TEXT)
|
||||
}
|
||||
}
|
||||
patchFlag: genFlagText(PatchFlags.TEXT),
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -303,30 +303,30 @@ describe('compiler: hoistStatic transform', () => {
|
|||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: { content: `_hoisted_1` },
|
||||
children: [{ type: NodeTypes.ELEMENT, tag: `Comp` }]
|
||||
}
|
||||
}
|
||||
children: [{ type: NodeTypes.ELEMENT, tag: `Comp` }],
|
||||
},
|
||||
},
|
||||
])
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('should hoist v-if props/children if static', () => {
|
||||
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([
|
||||
createObjectMatcher({
|
||||
key: `[0]`, // key injected by v-if branch
|
||||
id: 'foo'
|
||||
id: 'foo',
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"span"`
|
||||
tag: `"span"`,
|
||||
},
|
||||
hoistedChildrenArrayMatcher(2)
|
||||
hoistedChildrenArrayMatcher(2),
|
||||
])
|
||||
expect(
|
||||
((root.children[0] as ElementNode).children[0] as IfNode).codegenNode
|
||||
((root.children[0] as ElementNode).children[0] as IfNode).codegenNode,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
consequent: {
|
||||
|
@ -334,25 +334,25 @@ describe('compiler: hoistStatic transform', () => {
|
|||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: { content: `_hoisted_1` },
|
||||
children: { content: `_hoisted_3` }
|
||||
}
|
||||
children: { content: `_hoisted_3` },
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('should hoist v-for children if static', () => {
|
||||
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([
|
||||
createObjectMatcher({
|
||||
id: 'foo'
|
||||
id: 'foo',
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"span"`
|
||||
tag: `"span"`,
|
||||
},
|
||||
hoistedChildrenArrayMatcher(2)
|
||||
hoistedChildrenArrayMatcher(2),
|
||||
])
|
||||
const forBlockCodegen = (
|
||||
(root.children[0] as ElementNode).children[0] as ForNode
|
||||
|
@ -363,16 +363,16 @@ describe('compiler: hoistStatic transform', () => {
|
|||
props: undefined,
|
||||
children: {
|
||||
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]
|
||||
expect(innerBlockCodegen.returns).toMatchObject({
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
props: { content: `_hoisted_1` },
|
||||
children: { content: `_hoisted_3` }
|
||||
children: { content: `_hoisted_3` },
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -382,8 +382,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
const root = transformWithHoist(
|
||||
`<div><span>foo {{ 1 }} {{ true }}</span></div>`,
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
expect(root.hoists).toMatchObject([
|
||||
{
|
||||
|
@ -391,18 +391,18 @@ describe('compiler: hoistStatic transform', () => {
|
|||
tag: `"span"`,
|
||||
props: undefined,
|
||||
children: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION
|
||||
}
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
},
|
||||
},
|
||||
hoistedChildrenArrayMatcher()
|
||||
hoistedChildrenArrayMatcher(),
|
||||
])
|
||||
expect(root.codegenNode).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: undefined,
|
||||
children: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_hoisted_2`
|
||||
}
|
||||
content: `_hoisted_2`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -411,8 +411,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
const root = transformWithHoist(
|
||||
`<div><span :foo="0">{{ 1 }}</span></div>`,
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
|
||||
expect(root.hoists).toMatchObject([
|
||||
|
@ -425,19 +425,19 @@ describe('compiler: hoistStatic transform', () => {
|
|||
content: {
|
||||
content: `1`,
|
||||
isStatic: false,
|
||||
constType: ConstantTypes.CAN_STRINGIFY
|
||||
}
|
||||
}
|
||||
constType: ConstantTypes.CAN_STRINGIFY,
|
||||
},
|
||||
},
|
||||
},
|
||||
hoistedChildrenArrayMatcher()
|
||||
hoistedChildrenArrayMatcher(),
|
||||
])
|
||||
expect(root.codegenNode).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: undefined,
|
||||
children: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_hoisted_2`
|
||||
}
|
||||
content: `_hoisted_2`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -446,8 +446,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
const root = transformWithHoist(
|
||||
`<div><span :class="{ foo: true }">{{ bar }}</span></div>`,
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
|
||||
expect(root.hoists).toMatchObject([
|
||||
|
@ -458,7 +458,7 @@ describe('compiler: hoistStatic transform', () => {
|
|||
key: {
|
||||
content: `class`,
|
||||
isStatic: true,
|
||||
constType: ConstantTypes.CAN_STRINGIFY
|
||||
constType: ConstantTypes.CAN_STRINGIFY,
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
|
@ -467,13 +467,13 @@ describe('compiler: hoistStatic transform', () => {
|
|||
{
|
||||
content: `{ foo: true }`,
|
||||
isStatic: false,
|
||||
constType: ConstantTypes.CAN_STRINGIFY
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
constType: ConstantTypes.CAN_STRINGIFY,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
])
|
||||
expect(root.codegenNode).toMatchObject({
|
||||
tag: `"div"`,
|
||||
|
@ -486,20 +486,20 @@ describe('compiler: hoistStatic transform', () => {
|
|||
tag: `"span"`,
|
||||
props: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_hoisted_1`
|
||||
content: `_hoisted_1`,
|
||||
},
|
||||
children: {
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.bar`,
|
||||
isStatic: false,
|
||||
constType: ConstantTypes.NOT_CONSTANT
|
||||
}
|
||||
constType: ConstantTypes.NOT_CONSTANT,
|
||||
},
|
||||
},
|
||||
patchFlag: `1 /* TEXT */`
|
||||
}
|
||||
}
|
||||
]
|
||||
patchFlag: `1 /* TEXT */`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -508,8 +508,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
const root = transformWithHoist(
|
||||
`<div><p v-for="o in list"><span>{{ o }}</span></p></div>`,
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
|
||||
expect(root.hoists.length).toBe(0)
|
||||
|
@ -520,8 +520,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
const root = transformWithHoist(
|
||||
`<div><p v-for="o in list"><span>{{ o + 'foo' }}</span></p></div>`,
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
|
||||
expect(root.hoists.length).toBe(0)
|
||||
|
@ -532,8 +532,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
const root = transformWithHoist(
|
||||
`<Comp v-slot="{ foo }">{{ foo }}</Comp>`,
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
|
||||
expect(root.hoists.length).toBe(0)
|
||||
|
@ -545,8 +545,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
`<div><div><div @click="foo"/></div></div>`,
|
||||
{
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
}
|
||||
cacheHandlers: true,
|
||||
},
|
||||
)
|
||||
|
||||
expect(root.cached).toBe(1)
|
||||
|
@ -554,8 +554,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
expect(
|
||||
generate(root, {
|
||||
mode: 'module',
|
||||
prefixIdentifiers: true
|
||||
}).code
|
||||
prefixIdentifiers: true,
|
||||
}).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -564,8 +564,8 @@ describe('compiler: hoistStatic transform', () => {
|
|||
`<div><div><div :class="{}" @click="foo"/></div></div>`,
|
||||
{
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
}
|
||||
cacheHandlers: true,
|
||||
},
|
||||
)
|
||||
|
||||
expect(root.cached).toBe(1)
|
||||
|
@ -573,14 +573,14 @@ describe('compiler: hoistStatic transform', () => {
|
|||
expect(
|
||||
generate(root, {
|
||||
mode: 'module',
|
||||
prefixIdentifiers: true
|
||||
}).code
|
||||
prefixIdentifiers: true,
|
||||
}).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('should NOT hoist keyed template v-for with plain element child', () => {
|
||||
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(generate(root).code).toMatchSnapshot()
|
||||
|
@ -588,7 +588,7 @@ describe('compiler: hoistStatic transform', () => {
|
|||
|
||||
test('should NOT hoist SVG with directives', () => {
|
||||
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(generate(root).code).toMatchSnapshot()
|
||||
|
@ -596,13 +596,13 @@ describe('compiler: hoistStatic transform', () => {
|
|||
|
||||
test('clone hoisted array children in HMR mode', () => {
|
||||
const root = transformWithHoist(`<div><span class="hi"></span></div>`, {
|
||||
hmr: true
|
||||
hmr: true,
|
||||
})
|
||||
expect(root.hoists.length).toBe(2)
|
||||
expect(root.codegenNode).toMatchObject({
|
||||
children: {
|
||||
content: '[..._hoisted_2]'
|
||||
}
|
||||
content: '[..._hoisted_2]',
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {
|
||||
type ElementNode,
|
||||
type VNodeCall,
|
||||
noopDirectiveTransform,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
ElementNode,
|
||||
noopDirectiveTransform,
|
||||
VNodeCall
|
||||
} from '../../src'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
|
||||
|
@ -13,8 +13,8 @@ describe('compiler: noop directive transform', () => {
|
|||
transform(ast, {
|
||||
nodeTransforms: [transformElement],
|
||||
directiveTransforms: {
|
||||
noop: noopDirectiveTransform
|
||||
}
|
||||
noop: noopDirectiveTransform,
|
||||
},
|
||||
})
|
||||
const node = ast.children[0] as ElementNode
|
||||
// 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 {
|
||||
BindingTypes,
|
||||
type CompilerOptions,
|
||||
ConstantTypes,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
type InterpolationNode,
|
||||
NodeTypes,
|
||||
baseCompile,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
ElementNode,
|
||||
DirectiveNode,
|
||||
NodeTypes,
|
||||
CompilerOptions,
|
||||
InterpolationNode,
|
||||
ConstantTypes,
|
||||
BindingTypes,
|
||||
baseCompile
|
||||
} from '../../src'
|
||||
import { transformIf } from '../../src/transforms/vIf'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
|
@ -16,13 +16,13 @@ import { PatchFlagNames, PatchFlags } from '../../../shared/src'
|
|||
|
||||
function parseWithExpressionTransform(
|
||||
template: string,
|
||||
options: CompilerOptions = {}
|
||||
options: CompilerOptions = {},
|
||||
) {
|
||||
const ast = parse(template, options)
|
||||
transform(ast, {
|
||||
prefixIdentifiers: true,
|
||||
nodeTransforms: [transformIf, transformExpression],
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast.children[0]
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ describe('compiler: expression transform', () => {
|
|||
const node = parseWithExpressionTransform(`{{ foo }}`) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.foo`
|
||||
content: `_ctx.foo`,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -40,34 +40,34 @@ describe('compiler: expression transform', () => {
|
|||
const node = parseWithExpressionTransform(`{{}}`) as InterpolationNode
|
||||
const node2 = parseWithExpressionTransform(`{{ }}`) as InterpolationNode
|
||||
const node3 = parseWithExpressionTransform(
|
||||
`<div>{{ }}</div>`
|
||||
`<div>{{ }}</div>`,
|
||||
) as ElementNode
|
||||
|
||||
const objectToBeMatched = {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: ``
|
||||
content: ``,
|
||||
}
|
||||
expect(node.content).toMatchObject(objectToBeMatched)
|
||||
expect(node2.content).toMatchObject(objectToBeMatched)
|
||||
expect((node3.children[0] as InterpolationNode).content).toMatchObject(
|
||||
objectToBeMatched
|
||||
objectToBeMatched,
|
||||
)
|
||||
})
|
||||
|
||||
test('interpolation (children)', () => {
|
||||
const el = parseWithExpressionTransform(
|
||||
`<div>{{ foo }}</div>`
|
||||
`<div>{{ foo }}</div>`,
|
||||
) as ElementNode
|
||||
const node = el.children[0] as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.foo`
|
||||
content: `_ctx.foo`,
|
||||
})
|
||||
})
|
||||
|
||||
test('interpolation (complex)', () => {
|
||||
const el = parseWithExpressionTransform(
|
||||
`<div>{{ foo + bar(baz.qux) }}</div>`
|
||||
`<div>{{ foo + bar(baz.qux) }}</div>`,
|
||||
) as ElementNode
|
||||
const node = el.children[0] as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
|
@ -80,46 +80,46 @@ describe('compiler: expression transform', () => {
|
|||
{ content: `_ctx.baz` },
|
||||
`.`,
|
||||
{ content: `qux` },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('directive value', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`<div v-foo:arg="baz"/>`
|
||||
`<div v-foo:arg="baz"/>`,
|
||||
) as ElementNode
|
||||
const arg = (node.props[0] as DirectiveNode).arg!
|
||||
expect(arg).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `arg`
|
||||
content: `arg`,
|
||||
})
|
||||
const exp = (node.props[0] as DirectiveNode).exp!
|
||||
expect(exp).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.baz`
|
||||
content: `_ctx.baz`,
|
||||
})
|
||||
})
|
||||
|
||||
test('dynamic directive arg', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`<div v-foo:[arg]="baz"/>`
|
||||
`<div v-foo:[arg]="baz"/>`,
|
||||
) as ElementNode
|
||||
const arg = (node.props[0] as DirectiveNode).arg!
|
||||
expect(arg).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.arg`
|
||||
content: `_ctx.arg`,
|
||||
})
|
||||
const exp = (node.props[0] as DirectiveNode).exp!
|
||||
expect(exp).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.baz`
|
||||
content: `_ctx.baz`,
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix complex expressions', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ foo(baz + 1, { key: kuz }) }}`
|
||||
`{{ foo(baz + 1, { key: kuz }) }}`,
|
||||
) as InterpolationNode
|
||||
// should parse into compound expression
|
||||
expect(node.content).toMatchObject({
|
||||
|
@ -129,56 +129,56 @@ describe('compiler: expression transform', () => {
|
|||
content: `_ctx.foo`,
|
||||
loc: {
|
||||
start: { offset: 3, line: 1, column: 4 },
|
||||
end: { offset: 6, line: 1, column: 7 }
|
||||
}
|
||||
end: { offset: 6, line: 1, column: 7 },
|
||||
},
|
||||
},
|
||||
`(`,
|
||||
{
|
||||
content: `_ctx.baz`,
|
||||
loc: {
|
||||
start: { offset: 7, line: 1, column: 8 },
|
||||
end: { offset: 10, line: 1, column: 11 }
|
||||
}
|
||||
end: { offset: 10, line: 1, column: 11 },
|
||||
},
|
||||
},
|
||||
` + 1, { key: `,
|
||||
{
|
||||
content: `_ctx.kuz`,
|
||||
loc: {
|
||||
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', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ Math.max(1, 2) }}`
|
||||
`{{ Math.max(1, 2) }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [{ content: `Math` }, `.`, { content: `max` }, `(1, 2)`]
|
||||
children: [{ content: `Math` }, `.`, { content: `max` }, `(1, 2)`],
|
||||
})
|
||||
|
||||
expect(
|
||||
(parseWithExpressionTransform(`{{ new Error() }}`) as InterpolationNode)
|
||||
.content
|
||||
.content,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: ['new ', { content: 'Error' }, '()']
|
||||
children: ['new ', { content: 'Error' }, '()'],
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix reserved literals', () => {
|
||||
function assert(exp: string) {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ ${exp} }}`
|
||||
`{{ ${exp} }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: exp
|
||||
content: exp,
|
||||
})
|
||||
}
|
||||
assert(`true`)
|
||||
|
@ -189,7 +189,7 @@ describe('compiler: expression transform', () => {
|
|||
|
||||
test('should not prefix id of a function declaration', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ function foo() { return bar } }}`
|
||||
`{{ function foo() { return bar } }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -198,14 +198,14 @@ describe('compiler: expression transform', () => {
|
|||
{ content: `foo` },
|
||||
`() { return `,
|
||||
{ content: `_ctx.bar` },
|
||||
` }`
|
||||
]
|
||||
` }`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix params of a function expression', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ foo => foo + bar }}`
|
||||
`{{ foo => foo + bar }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -214,14 +214,14 @@ describe('compiler: expression transform', () => {
|
|||
` => `,
|
||||
{ content: `foo` },
|
||||
` + `,
|
||||
{ content: `_ctx.bar` }
|
||||
]
|
||||
{ content: `_ctx.bar` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix default value of a function expression param', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ (foo = baz) => foo + bar }}`
|
||||
`{{ (foo = baz) => foo + bar }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -233,14 +233,14 @@ describe('compiler: expression transform', () => {
|
|||
`) => `,
|
||||
{ content: `foo` },
|
||||
` + `,
|
||||
{ content: `_ctx.bar` }
|
||||
]
|
||||
{ content: `_ctx.bar` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix function param destructuring', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ ({ foo }) => foo + bar }}`
|
||||
`{{ ({ foo }) => foo + bar }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -250,14 +250,14 @@ describe('compiler: expression transform', () => {
|
|||
` }) => `,
|
||||
{ content: `foo` },
|
||||
` + `,
|
||||
{ content: `_ctx.bar` }
|
||||
]
|
||||
{ content: `_ctx.bar` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('function params should not affect out of scope identifiers', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ { a: foo => foo, b: foo } }}`
|
||||
`{{ { a: foo => foo, b: foo } }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -268,14 +268,14 @@ describe('compiler: expression transform', () => {
|
|||
{ content: `foo` },
|
||||
`, b: `,
|
||||
{ content: `_ctx.foo` },
|
||||
` }`
|
||||
]
|
||||
` }`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix default value of function param destructuring', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ ({ foo = bar }) => foo + bar }}`
|
||||
`{{ ({ foo = bar }) => foo + bar }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -287,13 +287,13 @@ describe('compiler: expression transform', () => {
|
|||
` }) => `,
|
||||
{ content: `foo` },
|
||||
` + `,
|
||||
{ content: `_ctx.bar` }
|
||||
]
|
||||
{ content: `_ctx.bar` },
|
||||
],
|
||||
})
|
||||
})
|
||||
test('should not prefix an object property key', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ { foo() { baz() }, value: bar } }}`
|
||||
`{{ { foo() { baz() }, value: bar } }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -302,24 +302,24 @@ describe('compiler: expression transform', () => {
|
|||
{ content: `_ctx.baz` },
|
||||
`() }, value: `,
|
||||
{ content: `_ctx.bar` },
|
||||
` }`
|
||||
]
|
||||
` }`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should not duplicate object key with same name as value', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ { foo: foo } }}`
|
||||
`{{ { foo: foo } }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`]
|
||||
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`],
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix a computed object property key', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ { [foo]: bar } }}`
|
||||
`{{ { [foo]: bar } }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -328,24 +328,24 @@ describe('compiler: expression transform', () => {
|
|||
{ content: `_ctx.foo` },
|
||||
`]: `,
|
||||
{ content: `_ctx.bar` },
|
||||
` }`
|
||||
]
|
||||
` }`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix object property shorthand value', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ { foo } }}`
|
||||
`{{ { foo } }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`]
|
||||
children: [`{ foo: `, { content: `_ctx.foo` }, ` }`],
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix id in a member expression', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ foo.bar.baz }}`
|
||||
`{{ foo.bar.baz }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -354,14 +354,14 @@ describe('compiler: expression transform', () => {
|
|||
`.`,
|
||||
{ content: `bar` },
|
||||
`.`,
|
||||
{ content: `baz` }
|
||||
]
|
||||
{ content: `baz` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix computed id in a member expression', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ foo[bar][baz] }}`
|
||||
`{{ foo[bar][baz] }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -371,8 +371,8 @@ describe('compiler: expression transform', () => {
|
|||
{ content: `_ctx.bar` },
|
||||
`][`,
|
||||
{ content: '_ctx.baz' },
|
||||
`]`
|
||||
]
|
||||
`]`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -380,23 +380,23 @@ describe('compiler: expression transform', () => {
|
|||
const onError = vi.fn()
|
||||
parseWithExpressionTransform(`{{ a( }}`, { onError })
|
||||
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', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ x = 1 }}`
|
||||
`{{ x = 1 }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [{ content: `_ctx.x` }, ` = 1`]
|
||||
children: [{ content: `_ctx.x` }, ` = 1`],
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix in assignment pattern', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ { x, y: [z] } = obj }}`
|
||||
`{{ { x, y: [z] } = obj }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -406,47 +406,47 @@ describe('compiler: expression transform', () => {
|
|||
`, y: [`,
|
||||
{ content: `_ctx.z` },
|
||||
`] } = `,
|
||||
{ content: `_ctx.obj` }
|
||||
]
|
||||
{ content: `_ctx.obj` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
// #8295
|
||||
test('should treat floating point number literals as constant', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ [1, 2.1] }}`
|
||||
`{{ [1, 2.1] }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
constType: ConstantTypes.CAN_STRINGIFY
|
||||
constType: ConstantTypes.CAN_STRINGIFY,
|
||||
})
|
||||
})
|
||||
|
||||
describe('ES Proposals support', () => {
|
||||
test('bigInt', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ 13000n }}`
|
||||
`{{ 13000n }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `13000n`,
|
||||
isStatic: false,
|
||||
constType: ConstantTypes.CAN_STRINGIFY
|
||||
constType: ConstantTypes.CAN_STRINGIFY,
|
||||
})
|
||||
})
|
||||
|
||||
test('nullish coalescing', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ a ?? b }}`
|
||||
`{{ a ?? b }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [{ content: `_ctx.a` }, ` ?? `, { content: `_ctx.b` }]
|
||||
children: [{ content: `_ctx.a` }, ` ?? `, { content: `_ctx.b` }],
|
||||
})
|
||||
})
|
||||
|
||||
test('optional chaining', () => {
|
||||
const node = parseWithExpressionTransform(
|
||||
`{{ a?.b?.c }}`
|
||||
`{{ a?.b?.c }}`,
|
||||
) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -455,8 +455,8 @@ describe('compiler: expression transform', () => {
|
|||
`?.`,
|
||||
{ content: `b` },
|
||||
`?.`,
|
||||
{ content: `c` }
|
||||
]
|
||||
{ content: `c` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -467,14 +467,18 @@ describe('compiler: expression transform', () => {
|
|||
[
|
||||
'pipelineOperator',
|
||||
{
|
||||
proposal: 'minimal'
|
||||
}
|
||||
]
|
||||
]
|
||||
proposal: 'minimal',
|
||||
},
|
||||
],
|
||||
],
|
||||
}) as InterpolationNode
|
||||
expect(node.content).toMatchObject({
|
||||
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,
|
||||
reactive: BindingTypes.SETUP_REACTIVE_CONST,
|
||||
literal: BindingTypes.LITERAL_CONST,
|
||||
isNaN: BindingTypes.SETUP_REF
|
||||
isNaN: BindingTypes.SETUP_REF,
|
||||
}
|
||||
|
||||
function compileWithBindingMetadata(
|
||||
template: string,
|
||||
options?: CompilerOptions
|
||||
options?: CompilerOptions,
|
||||
) {
|
||||
return baseCompile(template, {
|
||||
prefixIdentifiers: true,
|
||||
bindingMetadata,
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
test('non-inline mode', () => {
|
||||
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(`$setup.setup`)
|
||||
|
@ -521,7 +525,7 @@ describe('compiler: expression transform', () => {
|
|||
for (const x in list) {
|
||||
log(x)
|
||||
}
|
||||
}"/>`
|
||||
}"/>`,
|
||||
)
|
||||
expect(code).not.toMatch(`_ctx.x`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -533,7 +537,7 @@ describe('compiler: expression transform', () => {
|
|||
for (const x of list) {
|
||||
log(x)
|
||||
}
|
||||
}"/>`
|
||||
}"/>`,
|
||||
)
|
||||
expect(code).not.toMatch(`_ctx.x`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -545,7 +549,7 @@ describe('compiler: expression transform', () => {
|
|||
for (let i = 0; i < list.length; i++) {
|
||||
log(i)
|
||||
}
|
||||
}"/>`
|
||||
}"/>`,
|
||||
)
|
||||
expect(code).not.toMatch(`_ctx.i`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -554,7 +558,7 @@ describe('compiler: expression transform', () => {
|
|||
test('inline mode', () => {
|
||||
const { code } = compileWithBindingMetadata(
|
||||
`<div>{{ props }} {{ setup }} {{ setupConst }} {{ data }} {{ options }} {{ isNaN }}</div>`,
|
||||
{ inline: true }
|
||||
{ inline: true },
|
||||
)
|
||||
expect(code).toMatch(`__props.props`)
|
||||
expect(code).toMatch(`_unref(setup)`)
|
||||
|
@ -567,12 +571,12 @@ describe('compiler: expression transform', () => {
|
|||
|
||||
test('literal const handling', () => {
|
||||
const { code } = compileWithBindingMetadata(`<div>{{ literal }}</div>`, {
|
||||
inline: true
|
||||
inline: true,
|
||||
})
|
||||
expect(code).toMatch(`toDisplayString(literal)`)
|
||||
// #7973 should skip patch for literal const
|
||||
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)`)
|
||||
// #7973 should skip patch for literal const
|
||||
expect(code).not.toMatch(
|
||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
|
||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,
|
||||
)
|
||||
})
|
||||
|
||||
test('reactive const handling', () => {
|
||||
const { code } = compileWithBindingMetadata(`<div>{{ reactive }}</div>`, {
|
||||
inline: true
|
||||
inline: true,
|
||||
})
|
||||
// #7973 should not skip patch for reactive const
|
||||
expect(code).toMatch(
|
||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`
|
||||
`${PatchFlags.TEXT} /* ${PatchFlagNames[PatchFlags.TEXT]} */`,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {
|
||||
CompilerOptions,
|
||||
type CompilerOptions,
|
||||
type ElementNode,
|
||||
ErrorCodes,
|
||||
NodeTypes,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
ElementNode,
|
||||
NodeTypes,
|
||||
ErrorCodes
|
||||
} from '../../src'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { transformOn } from '../../src/transforms/vOn'
|
||||
|
@ -19,13 +19,13 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
|||
nodeTransforms: [
|
||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||
transformSlotOutlet,
|
||||
transformElement
|
||||
transformElement,
|
||||
],
|
||||
directiveTransforms: {
|
||||
on: transformOn,
|
||||
bind: transformBind
|
||||
bind: transformBind,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
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({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [`$slots`, `"foo"`]
|
||||
arguments: [`$slots`, `"foo"`],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -59,15 +59,15 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `foo`,
|
||||
isStatic: false
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('dynamically named slot outlet w/ prefixIdentifiers: true', () => {
|
||||
const ast = parseWithSlots(`<slot :name="foo + bar" />`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
|
@ -80,23 +80,23 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.foo`,
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
` + `,
|
||||
{
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.bar`,
|
||||
isStatic: false
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('default slot outlet with props', () => {
|
||||
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({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
|
@ -110,36 +110,36 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
{
|
||||
key: {
|
||||
content: `foo`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `bar`,
|
||||
isStatic: true
|
||||
}
|
||||
isStatic: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: {
|
||||
content: `baz`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `qux`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: {
|
||||
content: `fooBar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `foo-bar`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -158,26 +158,26 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
{
|
||||
key: {
|
||||
content: `foo`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `bar`,
|
||||
isStatic: true
|
||||
}
|
||||
isStatic: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: {
|
||||
content: `baz`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `qux`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -196,26 +196,26 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
{
|
||||
key: {
|
||||
content: `foo`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `bar`,
|
||||
isStatic: true
|
||||
}
|
||||
isStatic: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: {
|
||||
content: `baz`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `qux`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -234,11 +234,11 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: `div`
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tag: `div`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -257,11 +257,11 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: `div`
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tag: `div`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -279,14 +279,14 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
{
|
||||
key: {
|
||||
content: `foo`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `bar`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
|
@ -294,11 +294,11 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: `div`
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tag: `div`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -316,14 +316,14 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
{
|
||||
key: {
|
||||
content: `foo`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `bar`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
|
@ -331,11 +331,11 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: `div`
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
tag: `div`,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -344,11 +344,11 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
expect((ast.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [`$slots`, `"default"`, `{}`, `undefined`, `true`]
|
||||
arguments: [`$slots`, `"default"`, `{}`, `undefined`, `true`],
|
||||
})
|
||||
const fallback = parseWithSlots(`<slot>fallback</slot>`, {
|
||||
slotted: false,
|
||||
scopeId: 'foo'
|
||||
scopeId: 'foo',
|
||||
})
|
||||
|
||||
const child = {
|
||||
|
@ -357,14 +357,14 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `fallback`
|
||||
}
|
||||
]
|
||||
content: `fallback`,
|
||||
},
|
||||
],
|
||||
}
|
||||
expect((fallback.children[0] as ElementNode).codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: [`$slots`, `"default"`, `{}`, child, `true`]
|
||||
arguments: [`$slots`, `"default"`, `{}`, child, `true`],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -379,14 +379,14 @@ describe('compiler: transform <slot> outlets', () => {
|
|||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
column: index + 1,
|
||||
},
|
||||
end: {
|
||||
offset: index + 5,
|
||||
line: 1,
|
||||
column: index + 6
|
||||
}
|
||||
}
|
||||
column: index + 6,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import {
|
||||
CompilerOptions,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
type CompilerOptions,
|
||||
type ElementNode,
|
||||
type ForNode,
|
||||
NodeTypes,
|
||||
generate,
|
||||
ForNode,
|
||||
ElementNode
|
||||
baseParse as parse,
|
||||
transform,
|
||||
} from '../../src'
|
||||
import { transformFor } from '../../src/transforms/vFor'
|
||||
import { transformText } from '../../src/transforms/transformText'
|
||||
|
@ -22,9 +22,9 @@ function transformWithTextOpt(template: string, options: CompilerOptions = {}) {
|
|||
transformFor,
|
||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||
transformElement,
|
||||
transformText
|
||||
transformText,
|
||||
],
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -35,8 +35,8 @@ describe('compiler: transform text', () => {
|
|||
expect(root.children[0]).toMatchObject({
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -51,8 +51,8 @@ describe('compiler: transform text', () => {
|
|||
` + `,
|
||||
{ type: NodeTypes.TEXT, content: ` bar ` },
|
||||
` + `,
|
||||
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } }
|
||||
]
|
||||
{ type: NodeTypes.INTERPOLATION, content: { content: `baz` } },
|
||||
],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -75,12 +75,12 @@ describe('compiler: transform text', () => {
|
|||
` + `,
|
||||
{ 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(generate(root).code).toMatchSnapshot()
|
||||
|
@ -99,11 +99,11 @@ describe('compiler: transform text', () => {
|
|||
arguments: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `hello`
|
||||
}
|
||||
content: `hello`,
|
||||
},
|
||||
// should have no flag
|
||||
]
|
||||
}
|
||||
],
|
||||
},
|
||||
})
|
||||
expect(root.children[2].type).toBe(NodeTypes.ELEMENT)
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
@ -111,7 +111,7 @@ describe('compiler: transform text', () => {
|
|||
|
||||
test('consecutive text mixed with elements', () => {
|
||||
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[0].type).toBe(NodeTypes.ELEMENT)
|
||||
|
@ -128,12 +128,12 @@ describe('compiler: transform text', () => {
|
|||
` + `,
|
||||
{ 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[3]).toMatchObject({
|
||||
|
@ -144,10 +144,10 @@ describe('compiler: transform text', () => {
|
|||
arguments: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `hello`
|
||||
}
|
||||
]
|
||||
}
|
||||
content: `hello`,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
expect(root.children[4].type).toBe(NodeTypes.ELEMENT)
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
@ -155,21 +155,21 @@ describe('compiler: transform text', () => {
|
|||
|
||||
test('<template v-for>', () => {
|
||||
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)
|
||||
const forNode = root.children[0] as ForNode
|
||||
// should convert template v-for text children because they are inside
|
||||
// fragments
|
||||
expect(forNode.children[0]).toMatchObject({
|
||||
type: NodeTypes.TEXT_CALL
|
||||
type: NodeTypes.TEXT_CALL,
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('with prefixIdentifiers: true', () => {
|
||||
const root = transformWithTextOpt(`{{ foo }} bar {{ baz + qux }}`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(root.children.length).toBe(1)
|
||||
expect(root.children[0]).toMatchObject({
|
||||
|
@ -183,15 +183,15 @@ describe('compiler: transform text', () => {
|
|||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [{ content: `_ctx.baz` }, ` + `, { content: `_ctx.qux` }]
|
||||
}
|
||||
}
|
||||
]
|
||||
children: [{ content: `_ctx.baz` }, ` + `, { content: `_ctx.qux` }],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(
|
||||
generate(root, {
|
||||
prefixIdentifiers: true
|
||||
}).code
|
||||
prefixIdentifiers: true,
|
||||
}).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -210,12 +210,12 @@ describe('compiler: transform text', () => {
|
|||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'foo'
|
||||
}
|
||||
content: 'foo',
|
||||
},
|
||||
},
|
||||
genFlagText(PatchFlags.TEXT)
|
||||
]
|
||||
}
|
||||
genFlagText(PatchFlags.TEXT),
|
||||
],
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
import {
|
||||
type CallExpression,
|
||||
type CompilerOptions,
|
||||
type ElementNode,
|
||||
ErrorCodes,
|
||||
NodeTypes,
|
||||
type ObjectExpression,
|
||||
type VNodeCall,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
ElementNode,
|
||||
ObjectExpression,
|
||||
CompilerOptions,
|
||||
ErrorCodes,
|
||||
VNodeCall,
|
||||
NodeTypes,
|
||||
CallExpression
|
||||
} from '../../src'
|
||||
import { transformBind } from '../../src/transforms/vBind'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
import {
|
||||
CAMELIZE,
|
||||
NORMALIZE_PROPS,
|
||||
helperNameMap,
|
||||
NORMALIZE_PROPS
|
||||
} from '../../src/runtimeHelpers'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
|
||||
function parseWithVBind(
|
||||
template: string,
|
||||
options: CompilerOptions = {}
|
||||
options: CompilerOptions = {},
|
||||
): ElementNode {
|
||||
const ast = parse(template)
|
||||
transform(ast, {
|
||||
nodeTransforms: [
|
||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||
transformElement
|
||||
transformElement,
|
||||
],
|
||||
directiveTransforms: {
|
||||
bind: transformBind
|
||||
bind: transformBind,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast.children[0] as ElementNode
|
||||
}
|
||||
|
@ -47,13 +47,13 @@ describe('compiler: transform v-bind', () => {
|
|||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 13
|
||||
column: 13,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 15
|
||||
}
|
||||
}
|
||||
column: 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
|
@ -61,14 +61,14 @@ describe('compiler: transform v-bind', () => {
|
|||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 17
|
||||
column: 17,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 19
|
||||
}
|
||||
}
|
||||
}
|
||||
column: 19,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -81,17 +81,17 @@ describe('compiler: transform v-bind', () => {
|
|||
isStatic: true,
|
||||
loc: {
|
||||
start: { line: 1, column: 13, offset: 12 },
|
||||
end: { line: 1, column: 15, offset: 14 }
|
||||
}
|
||||
end: { line: 1, column: 15, offset: 14 },
|
||||
},
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false,
|
||||
loc: {
|
||||
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({
|
||||
key: {
|
||||
content: `id`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -123,16 +123,16 @@ describe('compiler: transform v-bind', () => {
|
|||
{
|
||||
key: {
|
||||
content: `id || ""`,
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -145,23 +145,23 @@ describe('compiler: transform v-bind', () => {
|
|||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 6
|
||||
column: 6,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 19
|
||||
}
|
||||
}
|
||||
column: 19,
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `arg`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: ``,
|
||||
isStatic: true
|
||||
}
|
||||
isStatic: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -171,12 +171,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `fooBar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -186,12 +186,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `fooBar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `fooBar`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -208,22 +208,22 @@ describe('compiler: transform v-bind', () => {
|
|||
{
|
||||
key: {
|
||||
content: `_${helperNameMap[CAMELIZE]}(foo || "")`,
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('.camel modifier w/ dynamic arg + prefixIdentifiers', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[foo(bar)].camel="id"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
||||
expect(props).toMatchObject({
|
||||
|
@ -243,17 +243,17 @@ describe('compiler: transform v-bind', () => {
|
|||
{ content: `_ctx.bar` },
|
||||
`)`,
|
||||
`) || ""`,
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
value: {
|
||||
content: `_ctx.id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -263,12 +263,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `.fooBar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -278,12 +278,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `.fooBar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `fooBar`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -300,22 +300,22 @@ describe('compiler: transform v-bind', () => {
|
|||
{
|
||||
key: {
|
||||
content: '`.${fooBar || ""}`',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('.prop modifier w/ dynamic arg + prefixIdentifiers', () => {
|
||||
const node = parseWithVBind(`<div v-bind:[foo(bar)].prop="id"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
const props = (node.codegenNode as VNodeCall).props as CallExpression
|
||||
expect(props).toMatchObject({
|
||||
|
@ -335,17 +335,17 @@ describe('compiler: transform v-bind', () => {
|
|||
{ content: `_ctx.bar` },
|
||||
`)`,
|
||||
`) || ""`,
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
value: {
|
||||
content: `_ctx.id`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -355,12 +355,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `.fooBar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -370,12 +370,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `.fooBar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `fooBar`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -385,12 +385,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `^foo-bar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `id`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -400,12 +400,12 @@ describe('compiler: transform v-bind', () => {
|
|||
expect(props.properties[0]).toMatchObject({
|
||||
key: {
|
||||
content: `^foo-bar`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: `fooBar`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -7,23 +7,23 @@ import { transformElement } from '../../src/transforms/transformElement'
|
|||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
import {
|
||||
ForNode,
|
||||
ConstantTypes,
|
||||
type ElementNode,
|
||||
type ForCodegenNode,
|
||||
type ForNode,
|
||||
type InterpolationNode,
|
||||
NodeTypes,
|
||||
SimpleExpressionNode,
|
||||
ElementNode,
|
||||
InterpolationNode,
|
||||
ForCodegenNode,
|
||||
ConstantTypes
|
||||
type SimpleExpressionNode,
|
||||
} from '../../src/ast'
|
||||
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 { PatchFlags } from '@vue/shared'
|
||||
import { createObjectMatcher, genFlagText } from '../testUtils'
|
||||
|
||||
function parseWithForTransform(
|
||||
template: string,
|
||||
options: CompilerOptions = {}
|
||||
options: CompilerOptions = {},
|
||||
) {
|
||||
const ast = parse(template, options)
|
||||
transform(ast, {
|
||||
|
@ -32,16 +32,16 @@ function parseWithForTransform(
|
|||
transformFor,
|
||||
...(options.prefixIdentifiers ? [transformExpression] : []),
|
||||
transformSlotOutlet,
|
||||
transformElement
|
||||
transformElement,
|
||||
],
|
||||
directiveTransforms: {
|
||||
bind: transformBind
|
||||
bind: transformBind,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return {
|
||||
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', () => {
|
||||
test('number expression', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="index in 5" />'
|
||||
'<span v-for="index in 5" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||
|
@ -59,7 +59,7 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('value', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="(item) in items" />'
|
||||
'<span v-for="(item) in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||
|
@ -69,31 +69,31 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('object de-structured value', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="({ id, value }) in items" />'
|
||||
'<span v-for="({ id, value }) in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
||||
'{ id, value }'
|
||||
'{ id, value }',
|
||||
)
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
})
|
||||
|
||||
test('array de-structured value', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="([ id, value ]) in items" />'
|
||||
'<span v-for="([ id, value ]) in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe(
|
||||
'[ id, value ]'
|
||||
'[ id, value ]',
|
||||
)
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
})
|
||||
|
||||
test('value and key', () => {
|
||||
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 as SimpleExpressionNode).content).toBe('key')
|
||||
|
@ -104,13 +104,13 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('value, key and index', () => {
|
||||
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 as SimpleExpressionNode).content).toBe('key')
|
||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||
'index'
|
||||
'index',
|
||||
)
|
||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
|
@ -118,12 +118,12 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('skipped key', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="(value,,index) in items" />'
|
||||
'<span v-for="(value,,index) in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||
'index'
|
||||
'index',
|
||||
)
|
||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
|
@ -131,12 +131,12 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('skipped value and key', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="(,,index) in items" />'
|
||||
'<span v-for="(,,index) in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||
'index'
|
||||
'index',
|
||||
)
|
||||
expect(forNode.valueAlias).toBeUndefined()
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
|
@ -144,7 +144,7 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('unbracketed value', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="item in items" />'
|
||||
'<span v-for="item in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).toBeUndefined()
|
||||
|
@ -154,7 +154,7 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('unbracketed value and key', () => {
|
||||
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 as SimpleExpressionNode).content).toBe('key')
|
||||
|
@ -165,13 +165,13 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('unbracketed value, key and index', () => {
|
||||
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 as SimpleExpressionNode).content).toBe('key')
|
||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||
'index'
|
||||
'index',
|
||||
)
|
||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
|
@ -179,12 +179,12 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('unbracketed skipped key', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for="value, , index in items" />'
|
||||
'<span v-for="value, , index in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||
'index'
|
||||
'index',
|
||||
)
|
||||
expect((forNode.valueAlias as SimpleExpressionNode).content).toBe('value')
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
|
@ -192,12 +192,12 @@ describe('compiler: v-for', () => {
|
|||
|
||||
test('unbracketed skipped value and key', () => {
|
||||
const { node: forNode } = parseWithForTransform(
|
||||
'<span v-for=", , index in items" />'
|
||||
'<span v-for=", , index in items" />',
|
||||
)
|
||||
expect(forNode.keyAlias).toBeUndefined()
|
||||
expect(forNode.objectIndexAlias).not.toBeUndefined()
|
||||
expect((forNode.objectIndexAlias as SimpleExpressionNode).content).toBe(
|
||||
'index'
|
||||
'index',
|
||||
)
|
||||
expect(forNode.valueAlias).toBeUndefined()
|
||||
expect((forNode.source as SimpleExpressionNode).content).toBe('items')
|
||||
|
@ -212,8 +212,8 @@ describe('compiler: v-for', () => {
|
|||
expect(onError).toHaveBeenCalledTimes(1)
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
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).toHaveBeenCalledWith(
|
||||
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).toHaveBeenCalledWith(
|
||||
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).toHaveBeenCalledWith(
|
||||
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).toHaveBeenCalledWith(
|
||||
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">
|
||||
<div :key="item.id"/>
|
||||
</template>`,
|
||||
{ onError }
|
||||
{ onError },
|
||||
)
|
||||
|
||||
expect(onError).toHaveBeenCalledTimes(1)
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
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
|
||||
|
@ -288,7 +288,7 @@ describe('compiler: v-for', () => {
|
|||
<template v-for="item in items">
|
||||
<div v-for="c in item.children" :key="c.id"/>
|
||||
</template>`,
|
||||
{ onError }
|
||||
{ onError },
|
||||
)
|
||||
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.end.line).toBe(1)
|
||||
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.end.line).toBe(1)
|
||||
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.end.line).toBe(1)
|
||||
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.end.line).toBe(1)
|
||||
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.end.line).toBe(1)
|
||||
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', () => {
|
||||
test('should prefix v-for source', () => {
|
||||
const { node } = parseWithForTransform(`<div v-for="i in list"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(node.source).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.list`
|
||||
content: `_ctx.list`,
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix v-for source w/ complex expression', () => {
|
||||
const { node } = parseWithForTransform(
|
||||
`<div v-for="i in list.concat([foo])"/>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(node.source).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -467,31 +467,31 @@ describe('compiler: v-for', () => {
|
|||
{ content: `concat` },
|
||||
`([`,
|
||||
{ content: `_ctx.foo` },
|
||||
`])`
|
||||
]
|
||||
`])`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix v-for alias', () => {
|
||||
const { node } = parseWithForTransform(
|
||||
`<div v-for="i in list">{{ i }}{{ j }}</div>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
const div = node.children[0] as ElementNode
|
||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `i`
|
||||
content: `i`,
|
||||
})
|
||||
expect((div.children[1] as InterpolationNode).content).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.j`
|
||||
content: `_ctx.j`,
|
||||
})
|
||||
})
|
||||
|
||||
test('should not prefix v-for aliases (multiple)', () => {
|
||||
const { node } = parseWithForTransform(
|
||||
`<div v-for="(i, j, k) in list">{{ i + j + k }}{{ l }}</div>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
const div = node.children[0] as ElementNode
|
||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||
|
@ -501,23 +501,23 @@ describe('compiler: v-for', () => {
|
|||
` + `,
|
||||
{ content: `j` },
|
||||
` + `,
|
||||
{ content: `k` }
|
||||
]
|
||||
{ content: `k` },
|
||||
],
|
||||
})
|
||||
expect((div.children[1] as InterpolationNode).content).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.l`
|
||||
content: `_ctx.l`,
|
||||
})
|
||||
})
|
||||
|
||||
test('should prefix id outside of v-for', () => {
|
||||
const { node } = parseWithForTransform(
|
||||
`<div><div v-for="i in list" />{{ i }}</div>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect((node.children[1] as InterpolationNode).content).toMatchObject({
|
||||
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">{{ i + j }}</div>{{ i }}
|
||||
</div>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
const outerDiv = node.children[0] as ElementNode
|
||||
const innerFor = outerDiv.children[0] as ForNode
|
||||
|
@ -534,7 +534,7 @@ describe('compiler: v-for', () => {
|
|||
.children[0] as InterpolationNode
|
||||
expect(innerExp.content).toMatchObject({
|
||||
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,
|
||||
|
@ -542,7 +542,7 @@ describe('compiler: v-for', () => {
|
|||
const outerExp = outerDiv.children[1] as InterpolationNode
|
||||
expect(outerExp.content).toMatchObject({
|
||||
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">
|
||||
{{ foo + bar + baz + qux + quux }}
|
||||
</div>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(node.valueAlias!).toMatchObject({
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
|
@ -564,8 +564,8 @@ describe('compiler: v-for', () => {
|
|||
{ content: `qux` },
|
||||
` = `,
|
||||
{ content: `_ctx.quux` },
|
||||
`] }`
|
||||
]
|
||||
`] }`,
|
||||
],
|
||||
})
|
||||
const div = node.children[0] as ElementNode
|
||||
expect((div.children[0] as InterpolationNode).content).toMatchObject({
|
||||
|
@ -579,17 +579,17 @@ describe('compiler: v-for', () => {
|
|||
` + `,
|
||||
{ content: `qux` },
|
||||
` + `,
|
||||
{ content: `_ctx.quux` }
|
||||
]
|
||||
{ content: `_ctx.quux` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('element v-for key expression prefixing', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform(
|
||||
'<div v-for="item in items" :key="itemKey(item)">test</div>',
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
const innerBlock = codegenNode.children.arguments[1].returns
|
||||
expect(innerBlock).toMatchObject({
|
||||
|
@ -604,20 +604,20 @@ describe('compiler: v-for', () => {
|
|||
`(`,
|
||||
// should NOT prefix in scope variables
|
||||
{ content: `item` },
|
||||
`)`
|
||||
]
|
||||
}
|
||||
})
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
// #2085
|
||||
test('template v-for key expression prefixing', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform(
|
||||
'<template v-for="item in items" :key="itemKey(item)">test</template>',
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
const innerBlock = codegenNode.children.arguments[1].returns
|
||||
expect(innerBlock).toMatchObject({
|
||||
|
@ -632,19 +632,19 @@ describe('compiler: v-for', () => {
|
|||
`(`,
|
||||
// should NOT prefix in scope variables
|
||||
{ content: `item` },
|
||||
`)`
|
||||
]
|
||||
}
|
||||
})
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
}),
|
||||
})
|
||||
})
|
||||
|
||||
test('template v-for key no prefixing on attribute key', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform(
|
||||
'<template v-for="item in items" key="key">test</template>',
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
const innerBlock = codegenNode.children.arguments[1].returns
|
||||
expect(innerBlock).toMatchObject({
|
||||
|
@ -653,9 +653,9 @@ describe('compiler: v-for', () => {
|
|||
props: createObjectMatcher({
|
||||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'key'
|
||||
}
|
||||
})
|
||||
content: 'key',
|
||||
},
|
||||
}),
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -665,7 +665,7 @@ describe('compiler: v-for', () => {
|
|||
node: ForCodegenNode,
|
||||
keyed: boolean = false,
|
||||
customReturn: boolean = false,
|
||||
disableTracking: boolean = true
|
||||
disableTracking: boolean = true,
|
||||
) {
|
||||
expect(node).toMatchObject({
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
|
@ -687,32 +687,34 @@ describe('compiler: v-for', () => {
|
|||
? {}
|
||||
: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
isBlock: disableTracking
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
isBlock: disableTracking,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
const renderListArgs = node.children.arguments
|
||||
return {
|
||||
source: renderListArgs[0] as SimpleExpressionNode,
|
||||
params: (renderListArgs[1] as any).params,
|
||||
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', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<span v-for="(item) in items" />')
|
||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||
source: { content: `items` },
|
||||
params: [{ content: `item` }],
|
||||
innerVNodeCall: {
|
||||
tag: `"span"`
|
||||
}
|
||||
tag: `"span"`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -720,11 +722,11 @@ describe('compiler: v-for', () => {
|
|||
test('value + key + index', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<span v-for="(item, key, index) in items" />')
|
||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||
source: { content: `items` },
|
||||
params: [{ content: `item` }, { content: `key` }, { content: `index` }]
|
||||
params: [{ content: `item` }, { content: `key` }, { content: `index` }],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -732,11 +734,11 @@ describe('compiler: v-for', () => {
|
|||
test('skipped value', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<span v-for="(, key, index) in items" />')
|
||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||
source: { content: `items` },
|
||||
params: [{ content: `_` }, { content: `key` }, { content: `index` }]
|
||||
params: [{ content: `_` }, { content: `key` }, { content: `index` }],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -744,11 +746,11 @@ describe('compiler: v-for', () => {
|
|||
test('skipped key', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<span v-for="(item,,index) in items" />')
|
||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||
source: { content: `items` },
|
||||
params: [{ content: `item` }, { content: `__` }, { content: `index` }]
|
||||
params: [{ content: `item` }, { content: `__` }, { content: `index` }],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -756,11 +758,11 @@ describe('compiler: v-for', () => {
|
|||
test('skipped value & key', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<span v-for="(,,index) in items" />')
|
||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||
source: { content: `items` },
|
||||
params: [{ content: `_` }, { content: `__` }, { content: `index` }]
|
||||
params: [{ content: `_` }, { content: `__` }, { content: `index` }],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -768,9 +770,9 @@ describe('compiler: v-for', () => {
|
|||
test('v-for with constant expression', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<p v-for="item in 10">{{item}}</p>', {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
|
||||
expect(
|
||||
|
@ -778,8 +780,8 @@ describe('compiler: v-for', () => {
|
|||
codegenNode,
|
||||
false /* keyed */,
|
||||
false /* customReturn */,
|
||||
false /* disableTracking */
|
||||
)
|
||||
false /* disableTracking */,
|
||||
),
|
||||
).toMatchObject({
|
||||
source: { content: `10`, constType: ConstantTypes.CAN_STRINGIFY },
|
||||
params: [{ content: `item` }],
|
||||
|
@ -793,11 +795,11 @@ describe('compiler: v-for', () => {
|
|||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'item',
|
||||
isStatic: false,
|
||||
constType: ConstantTypes.NOT_CONSTANT
|
||||
}
|
||||
constType: ConstantTypes.NOT_CONSTANT,
|
||||
},
|
||||
},
|
||||
patchFlag: genFlagText(PatchFlags.TEXT)
|
||||
}
|
||||
patchFlag: genFlagText(PatchFlags.TEXT),
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -805,9 +807,9 @@ describe('compiler: v-for', () => {
|
|||
test('template v-for', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform(
|
||||
'<template v-for="item in items">hello<span/></template>'
|
||||
'<template v-for="item in items">hello<span/></template>',
|
||||
)
|
||||
expect(assertSharedCodegen(codegenNode)).toMatchObject({
|
||||
source: { content: `items` },
|
||||
|
@ -818,10 +820,10 @@ describe('compiler: v-for', () => {
|
|||
isBlock: true,
|
||||
children: [
|
||||
{ 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()
|
||||
})
|
||||
|
@ -829,19 +831,19 @@ describe('compiler: v-for', () => {
|
|||
test('template v-for w/ <slot/>', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform(
|
||||
'<template v-for="item in items"><slot/></template>'
|
||||
'<template v-for="item in items"><slot/></template>',
|
||||
)
|
||||
expect(
|
||||
assertSharedCodegen(codegenNode, false, true /* custom return */)
|
||||
assertSharedCodegen(codegenNode, false, true /* custom return */),
|
||||
).toMatchObject({
|
||||
source: { content: `items` },
|
||||
params: [{ content: `item` }],
|
||||
returns: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT
|
||||
}
|
||||
callee: RENDER_SLOT,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -850,9 +852,9 @@ describe('compiler: v-for', () => {
|
|||
test('template v-for key injection with single child', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = 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({
|
||||
source: { content: `items` },
|
||||
|
@ -862,9 +864,9 @@ describe('compiler: v-for', () => {
|
|||
tag: `"span"`,
|
||||
props: createObjectMatcher({
|
||||
key: '[item.id]',
|
||||
id: '[item.id]'
|
||||
})
|
||||
}
|
||||
id: '[item.id]',
|
||||
}),
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -872,17 +874,17 @@ describe('compiler: v-for', () => {
|
|||
test('v-for on <slot/>', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<slot v-for="item in items"></slot>')
|
||||
expect(
|
||||
assertSharedCodegen(codegenNode, false, true /* custom return */)
|
||||
assertSharedCodegen(codegenNode, false, true /* custom return */),
|
||||
).toMatchObject({
|
||||
source: { content: `items` },
|
||||
params: [{ content: `item` }],
|
||||
returns: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT
|
||||
}
|
||||
callee: RENDER_SLOT,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -890,7 +892,7 @@ describe('compiler: v-for', () => {
|
|||
test('keyed v-for', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<span v-for="(item) in items" :key="item" />')
|
||||
expect(assertSharedCodegen(codegenNode, true)).toMatchObject({
|
||||
source: { content: `items` },
|
||||
|
@ -898,9 +900,9 @@ describe('compiler: v-for', () => {
|
|||
innerVNodeCall: {
|
||||
tag: `"span"`,
|
||||
props: createObjectMatcher({
|
||||
key: `[item]`
|
||||
})
|
||||
}
|
||||
key: `[item]`,
|
||||
}),
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -908,9 +910,9 @@ describe('compiler: v-for', () => {
|
|||
test('keyed template v-for', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = 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({
|
||||
source: { content: `items` },
|
||||
|
@ -918,14 +920,14 @@ describe('compiler: v-for', () => {
|
|||
innerVNodeCall: {
|
||||
tag: FRAGMENT,
|
||||
props: createObjectMatcher({
|
||||
key: `[item]`
|
||||
key: `[item]`,
|
||||
}),
|
||||
children: [
|
||||
{ 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()
|
||||
})
|
||||
|
@ -933,7 +935,7 @@ describe('compiler: v-for', () => {
|
|||
test('v-if + v-for', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform(`<div v-if="ok" v-for="i in list"/>`)
|
||||
expect(codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
|
@ -941,7 +943,7 @@ describe('compiler: v-for', () => {
|
|||
consequent: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
props: createObjectMatcher({
|
||||
key: `[0]`
|
||||
key: `[0]`,
|
||||
}),
|
||||
isBlock: true,
|
||||
disableTracking: true,
|
||||
|
@ -957,12 +959,12 @@ describe('compiler: v-for', () => {
|
|||
returns: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`,
|
||||
isBlock: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
isBlock: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -971,7 +973,7 @@ describe('compiler: v-for', () => {
|
|||
test('v-if + v-for on <template>', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform(`<template v-if="ok" v-for="i in list"/>`)
|
||||
expect(codegenNode).toMatchObject({
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
|
@ -979,7 +981,7 @@ describe('compiler: v-for', () => {
|
|||
consequent: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
props: createObjectMatcher({
|
||||
key: `[0]`
|
||||
key: `[0]`,
|
||||
}),
|
||||
isBlock: true,
|
||||
disableTracking: true,
|
||||
|
@ -995,12 +997,12 @@ describe('compiler: v-for', () => {
|
|||
returns: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: FRAGMENT,
|
||||
isBlock: true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
isBlock: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -1008,12 +1010,12 @@ describe('compiler: v-for', () => {
|
|||
test('v-for on element with custom directive', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithForTransform('<div v-for="i in list" v-foo/>')
|
||||
const { returns } = assertSharedCodegen(codegenNode, false, true)
|
||||
expect(returns).toMatchObject({
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION }
|
||||
directives: { type: NodeTypes.JS_ARRAY_EXPRESSION },
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
|
|
@ -4,26 +4,26 @@ import { transformIf } from '../../src/transforms/vIf'
|
|||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||
import {
|
||||
CommentNode,
|
||||
ConditionalExpression,
|
||||
ElementNode,
|
||||
type CommentNode,
|
||||
type ConditionalExpression,
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
IfBranchNode,
|
||||
IfConditionalExpression,
|
||||
IfNode,
|
||||
type IfBranchNode,
|
||||
type IfConditionalExpression,
|
||||
type IfNode,
|
||||
NodeTypes,
|
||||
SimpleExpressionNode,
|
||||
TextNode,
|
||||
VNodeCall
|
||||
type SimpleExpressionNode,
|
||||
type TextNode,
|
||||
type VNodeCall,
|
||||
} from '../../src/ast'
|
||||
import { ErrorCodes } from '../../src/errors'
|
||||
import { CompilerOptions, generate, TO_HANDLERS } from '../../src'
|
||||
import { type CompilerOptions, TO_HANDLERS, generate } from '../../src'
|
||||
import {
|
||||
CREATE_COMMENT,
|
||||
FRAGMENT,
|
||||
MERGE_PROPS,
|
||||
NORMALIZE_PROPS,
|
||||
RENDER_SLOT
|
||||
RENDER_SLOT,
|
||||
} from '../../src/runtimeHelpers'
|
||||
import { createObjectMatcher } from '../testUtils'
|
||||
|
||||
|
@ -31,12 +31,12 @@ function parseWithIfTransform(
|
|||
template: string,
|
||||
options: CompilerOptions = {},
|
||||
returnIndex: number = 0,
|
||||
childrenLen: number = 1
|
||||
childrenLen: number = 1,
|
||||
) {
|
||||
const ast = parse(template, options)
|
||||
transform(ast, {
|
||||
nodeTransforms: [transformIf, transformSlotOutlet, transformElement],
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
if (!options.onError) {
|
||||
expect(ast.children.length).toBe(childrenLen)
|
||||
|
@ -48,7 +48,7 @@ function parseWithIfTransform(
|
|||
root: ast,
|
||||
node: ast.children[returnIndex] as IfNode & {
|
||||
codegenNode: IfConditionalExpression
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ describe('compiler: v-if', () => {
|
|||
expect(node.type).toBe(NodeTypes.IF)
|
||||
expect(node.branches.length).toBe(1)
|
||||
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
|
||||
`ok`
|
||||
`ok`,
|
||||
)
|
||||
expect(node.branches[0].children.length).toBe(1)
|
||||
expect(node.branches[0].children[0].type).toBe(NodeTypes.ELEMENT)
|
||||
|
@ -68,12 +68,12 @@ describe('compiler: v-if', () => {
|
|||
|
||||
test('template v-if', () => {
|
||||
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.branches.length).toBe(1)
|
||||
expect((node.branches[0].condition as SimpleExpressionNode).content).toBe(
|
||||
`ok`
|
||||
`ok`,
|
||||
)
|
||||
expect(node.branches[0].children.length).toBe(3)
|
||||
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.branches.length).toBe(1)
|
||||
expect((node.branches[0].children[0] as ElementNode).tag).toBe(
|
||||
`Component`
|
||||
`Component`,
|
||||
)
|
||||
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
|
||||
// element, it still needs to be made a block
|
||||
expect(
|
||||
((node.branches[0].children[0] as ElementNode)!
|
||||
.codegenNode as VNodeCall)!.isBlock
|
||||
.codegenNode as VNodeCall)!.isBlock,
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
|
@ -122,7 +122,7 @@ describe('compiler: v-if', () => {
|
|||
|
||||
test('v-if + v-else-if', () => {
|
||||
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.branches.length).toBe(2)
|
||||
|
@ -142,7 +142,7 @@ describe('compiler: v-if', () => {
|
|||
|
||||
test('v-if + v-else-if + v-else', () => {
|
||||
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.branches.length).toBe(3)
|
||||
|
@ -202,11 +202,11 @@ describe('compiler: v-if', () => {
|
|||
|
||||
test('should prefix v-if condition', () => {
|
||||
const { node } = parseWithIfTransform(`<div v-if="ok"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(node.branches[0].condition).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.ok`
|
||||
content: `_ctx.ok`,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -219,32 +219,32 @@ describe('compiler: v-if', () => {
|
|||
expect(onError.mock.calls[0]).toMatchObject([
|
||||
{
|
||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||
loc: node1.loc
|
||||
}
|
||||
loc: node1.loc,
|
||||
},
|
||||
])
|
||||
|
||||
const { node: node2 } = parseWithIfTransform(
|
||||
`<div/><div v-else/>`,
|
||||
{ onError },
|
||||
1
|
||||
1,
|
||||
)
|
||||
expect(onError.mock.calls[1]).toMatchObject([
|
||||
{
|
||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||
loc: node2.loc
|
||||
}
|
||||
loc: node2.loc,
|
||||
},
|
||||
])
|
||||
|
||||
const { node: node3 } = parseWithIfTransform(
|
||||
`<div/>foo<div v-else/>`,
|
||||
{ onError },
|
||||
2
|
||||
2,
|
||||
)
|
||||
expect(onError.mock.calls[2]).toMatchObject([
|
||||
{
|
||||
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 { node: node1 } = parseWithIfTransform(`<div v-else-if="foo"/>`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
expect(onError.mock.calls[0]).toMatchObject([
|
||||
{
|
||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||
loc: node1.loc
|
||||
}
|
||||
loc: node1.loc,
|
||||
},
|
||||
])
|
||||
|
||||
const { node: node2 } = parseWithIfTransform(
|
||||
`<div/><div v-else-if="foo"/>`,
|
||||
{ onError },
|
||||
1
|
||||
1,
|
||||
)
|
||||
expect(onError.mock.calls[1]).toMatchObject([
|
||||
{
|
||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||
loc: node2.loc
|
||||
}
|
||||
loc: node2.loc,
|
||||
},
|
||||
])
|
||||
|
||||
const { node: node3 } = parseWithIfTransform(
|
||||
`<div/>foo<div v-else-if="foo"/>`,
|
||||
{ onError },
|
||||
2
|
||||
2,
|
||||
)
|
||||
expect(onError.mock.calls[2]).toMatchObject([
|
||||
{
|
||||
code: ErrorCodes.X_V_ELSE_NO_ADJACENT_IF,
|
||||
loc: node3.loc
|
||||
}
|
||||
loc: node3.loc,
|
||||
},
|
||||
])
|
||||
|
||||
const {
|
||||
node: { branches }
|
||||
node: { branches },
|
||||
} = parseWithIfTransform(
|
||||
`<div v-if="notOk"/><div v-else/><div v-else-if="ok"/>`,
|
||||
{ onError },
|
||||
0
|
||||
0,
|
||||
)
|
||||
|
||||
expect(onError.mock.calls[3]).toMatchObject([
|
||||
{
|
||||
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
|
||||
parseWithIfTransform(
|
||||
`<div v-if="ok" :key="a + 1" /><div v-else :key="a + 1" />`,
|
||||
{ onError }
|
||||
{ onError },
|
||||
)
|
||||
expect(onError.mock.calls[0]).toMatchObject([
|
||||
{
|
||||
code: ErrorCodes.X_V_IF_SAME_KEY
|
||||
}
|
||||
code: ErrorCodes.X_V_IF_SAME_KEY,
|
||||
},
|
||||
])
|
||||
// static
|
||||
parseWithIfTransform(`<div v-if="ok" key="1" /><div v-else key="1" />`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
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(
|
||||
node: IfConditionalExpression,
|
||||
depth: number = 0,
|
||||
hasElse: boolean = false
|
||||
hasElse: boolean = false,
|
||||
) {
|
||||
expect(node).toMatchObject({
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
test: {
|
||||
content: `ok`
|
||||
content: `ok`,
|
||||
},
|
||||
consequent: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
isBlock: true
|
||||
isBlock: true,
|
||||
},
|
||||
alternate:
|
||||
depth < 1
|
||||
? hasElse
|
||||
? {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
isBlock: true
|
||||
isBlock: true,
|
||||
}
|
||||
: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_COMMENT
|
||||
callee: CREATE_COMMENT,
|
||||
}
|
||||
: {
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
test: {
|
||||
content: `orNot`
|
||||
content: `orNot`,
|
||||
},
|
||||
consequent: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
isBlock: true
|
||||
isBlock: true,
|
||||
},
|
||||
alternate: hasElse
|
||||
? {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
isBlock: true
|
||||
isBlock: true,
|
||||
}
|
||||
: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_COMMENT
|
||||
}
|
||||
}
|
||||
callee: CREATE_COMMENT,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
test('basic v-if', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok"/>`)
|
||||
assertSharedCodegen(codegenNode)
|
||||
expect(codegenNode.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[0]` })
|
||||
props: createObjectMatcher({ key: `[0]` }),
|
||||
})
|
||||
expect(codegenNode.alternate).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_COMMENT
|
||||
callee: CREATE_COMMENT,
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -393,7 +393,7 @@ describe('compiler: v-if', () => {
|
|||
test('template v-if', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<template v-if="ok"><div/>hello<p/></template>`)
|
||||
assertSharedCodegen(codegenNode)
|
||||
expect(codegenNode.consequent).toMatchObject({
|
||||
|
@ -402,12 +402,12 @@ describe('compiler: v-if', () => {
|
|||
children: [
|
||||
{ type: NodeTypes.ELEMENT, tag: 'div' },
|
||||
{ type: NodeTypes.TEXT, content: `hello` },
|
||||
{ type: NodeTypes.ELEMENT, tag: 'p' }
|
||||
]
|
||||
{ type: NodeTypes.ELEMENT, tag: 'p' },
|
||||
],
|
||||
})
|
||||
expect(codegenNode.alternate).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_COMMENT
|
||||
callee: CREATE_COMMENT,
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -415,12 +415,12 @@ describe('compiler: v-if', () => {
|
|||
test('template v-if w/ single <slot/> child', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<template v-if="ok"><slot/></template>`)
|
||||
expect(codegenNode.consequent).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
|
||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -428,12 +428,12 @@ describe('compiler: v-if', () => {
|
|||
test('v-if on <slot/>', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<slot v-if="ok"></slot>`)
|
||||
expect(codegenNode.consequent).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT,
|
||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })]
|
||||
arguments: ['$slots', '"default"', createObjectMatcher({ key: `[0]` })],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -441,16 +441,16 @@ describe('compiler: v-if', () => {
|
|||
test('v-if + v-else', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok"/><p v-else/>`)
|
||||
assertSharedCodegen(codegenNode, 0, true)
|
||||
expect(codegenNode.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[0]` })
|
||||
props: createObjectMatcher({ key: `[0]` }),
|
||||
})
|
||||
expect(codegenNode.alternate).toMatchObject({
|
||||
tag: `"p"`,
|
||||
props: createObjectMatcher({ key: `[1]` })
|
||||
props: createObjectMatcher({ key: `[1]` }),
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -458,17 +458,17 @@ describe('compiler: v-if', () => {
|
|||
test('v-if + v-else-if', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok"/><p v-else-if="orNot" />`)
|
||||
assertSharedCodegen(codegenNode, 1)
|
||||
expect(codegenNode.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[0]` })
|
||||
props: createObjectMatcher({ key: `[0]` }),
|
||||
})
|
||||
const branch2 = codegenNode.alternate as ConditionalExpression
|
||||
expect(branch2.consequent).toMatchObject({
|
||||
tag: `"p"`,
|
||||
props: createObjectMatcher({ key: `[1]` })
|
||||
props: createObjectMatcher({ key: `[1]` }),
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -476,19 +476,19 @@ describe('compiler: v-if', () => {
|
|||
test('v-if + v-else-if + v-else', () => {
|
||||
const {
|
||||
root,
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = 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)
|
||||
expect(codegenNode.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[0]` })
|
||||
props: createObjectMatcher({ key: `[0]` }),
|
||||
})
|
||||
const branch2 = codegenNode.alternate as ConditionalExpression
|
||||
expect(branch2.consequent).toMatchObject({
|
||||
tag: `"p"`,
|
||||
props: createObjectMatcher({ key: `[1]` })
|
||||
props: createObjectMatcher({ key: `[1]` }),
|
||||
})
|
||||
expect(branch2.alternate).toMatchObject({
|
||||
tag: FRAGMENT,
|
||||
|
@ -496,9 +496,9 @@ describe('compiler: v-if', () => {
|
|||
children: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `fine`
|
||||
}
|
||||
]
|
||||
content: `fine`,
|
||||
},
|
||||
],
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -508,7 +508,7 @@ describe('compiler: v-if', () => {
|
|||
`<div v-if="ok"/><p v-if="orNot"/>`,
|
||||
{},
|
||||
0 /* returnIndex, just give the default value */,
|
||||
2 /* childrenLen */
|
||||
2 /* childrenLen */,
|
||||
)
|
||||
|
||||
const ifNode = root.children[0] as IfNode & {
|
||||
|
@ -516,14 +516,14 @@ describe('compiler: v-if', () => {
|
|||
}
|
||||
expect(ifNode.codegenNode.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[0]` })
|
||||
props: createObjectMatcher({ key: `[0]` }),
|
||||
})
|
||||
const ifNode2 = root.children[1] as IfNode & {
|
||||
codegenNode: IfConditionalExpression
|
||||
}
|
||||
expect(ifNode2.codegenNode.consequent).toMatchObject({
|
||||
tag: `"p"`,
|
||||
props: createObjectMatcher({ key: `[1]` })
|
||||
props: createObjectMatcher({ key: `[1]` }),
|
||||
})
|
||||
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/>`,
|
||||
{},
|
||||
0 /* returnIndex, just give the default value */,
|
||||
2 /* childrenLen */
|
||||
2 /* childrenLen */,
|
||||
)
|
||||
const ifNode = root.children[0] as IfNode & {
|
||||
codegenNode: IfConditionalExpression
|
||||
}
|
||||
expect(ifNode.codegenNode.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[0]` })
|
||||
props: createObjectMatcher({ key: `[0]` }),
|
||||
})
|
||||
expect(ifNode.codegenNode.alternate).toMatchObject({
|
||||
tag: `"p"`,
|
||||
props: createObjectMatcher({ key: `[1]` })
|
||||
props: createObjectMatcher({ key: `[1]` }),
|
||||
})
|
||||
const ifNode2 = root.children[1] as IfNode & {
|
||||
codegenNode: IfConditionalExpression
|
||||
}
|
||||
expect(ifNode2.codegenNode.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[2]` })
|
||||
props: createObjectMatcher({ key: `[2]` }),
|
||||
})
|
||||
const branch = ifNode2.codegenNode.alternate as IfConditionalExpression
|
||||
expect(branch.consequent).toMatchObject({
|
||||
tag: `"p"`,
|
||||
props: createObjectMatcher({ key: `[3]` })
|
||||
props: createObjectMatcher({ key: `[3]` }),
|
||||
})
|
||||
expect(branch.alternate).toMatchObject({
|
||||
tag: `"p"`,
|
||||
props: createObjectMatcher({ key: `[4]` })
|
||||
props: createObjectMatcher({ key: `[4]` }),
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('key injection (only v-bind)', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok" v-bind="obj"/>`)
|
||||
const branch1 = codegenNode.consequent as VNodeCall
|
||||
expect(branch1.props).toMatchObject({
|
||||
|
@ -577,15 +577,18 @@ describe('compiler: v-if', () => {
|
|||
{
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: MERGE_PROPS,
|
||||
arguments: [createObjectMatcher({ key: `[0]` }), { content: `obj` }]
|
||||
}
|
||||
]
|
||||
arguments: [
|
||||
createObjectMatcher({ key: `[0]` }),
|
||||
{ content: `obj` },
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('key injection (before v-bind)', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok" id="foo" v-bind="obj"/>`)
|
||||
const branch1 = codegenNode.consequent as VNodeCall
|
||||
expect(branch1.props).toMatchObject({
|
||||
|
@ -594,16 +597,16 @@ describe('compiler: v-if', () => {
|
|||
arguments: [
|
||||
createObjectMatcher({
|
||||
key: '[0]',
|
||||
id: 'foo'
|
||||
id: 'foo',
|
||||
}),
|
||||
{ content: `obj` }
|
||||
]
|
||||
{ content: `obj` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('key injection (after v-bind)', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok" v-bind="obj" id="foo"/>`)
|
||||
const branch1 = codegenNode.consequent as VNodeCall
|
||||
expect(branch1.props).toMatchObject({
|
||||
|
@ -613,15 +616,15 @@ describe('compiler: v-if', () => {
|
|||
createObjectMatcher({ key: `[0]` }),
|
||||
{ content: `obj` },
|
||||
createObjectMatcher({
|
||||
id: 'foo'
|
||||
})
|
||||
]
|
||||
id: 'foo',
|
||||
}),
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('key injection (w/ custom directive)', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok" v-foo />`)
|
||||
const branch1 = codegenNode.consequent as VNodeCall
|
||||
expect(branch1.directives).not.toBeUndefined()
|
||||
|
@ -631,7 +634,7 @@ describe('compiler: v-if', () => {
|
|||
// #6631
|
||||
test('avoid duplicate keys', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = parseWithIfTransform(`<div v-if="ok" key="custom_key" v-bind="obj"/>`)
|
||||
const branch1 = codegenNode.consequent as VNodeCall
|
||||
expect(branch1.props).toMatchObject({
|
||||
|
@ -639,31 +642,31 @@ describe('compiler: v-if', () => {
|
|||
callee: MERGE_PROPS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
key: 'custom_key'
|
||||
key: 'custom_key',
|
||||
}),
|
||||
{ content: `obj` }
|
||||
]
|
||||
{ content: `obj` },
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('with spaces between branches', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = 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({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[0]` })
|
||||
props: createObjectMatcher({ key: `[0]` }),
|
||||
})
|
||||
const branch = codegenNode.alternate as ConditionalExpression
|
||||
expect(branch.consequent).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[1]` })
|
||||
props: createObjectMatcher({ key: `[1]` }),
|
||||
})
|
||||
expect(branch.alternate).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({ key: `[2]` })
|
||||
props: createObjectMatcher({ key: `[2]` }),
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -729,7 +732,7 @@ describe('compiler: v-if', () => {
|
|||
<p/>
|
||||
</template>
|
||||
`,
|
||||
{ comments: true }
|
||||
{ comments: true },
|
||||
)
|
||||
__DEV__ = true
|
||||
})
|
||||
|
@ -737,21 +740,21 @@ describe('compiler: v-if', () => {
|
|||
|
||||
test('v-on with v-if', () => {
|
||||
const {
|
||||
node: { codegenNode }
|
||||
node: { codegenNode },
|
||||
} = 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(
|
||||
NodeTypes.JS_CALL_EXPRESSION
|
||||
NodeTypes.JS_CALL_EXPRESSION,
|
||||
)
|
||||
expect((codegenNode.consequent as any).props.callee).toBe(MERGE_PROPS)
|
||||
expect(
|
||||
(codegenNode.consequent as any).props.arguments[0].properties[0].value
|
||||
.content
|
||||
.content,
|
||||
).toBe('0')
|
||||
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) {
|
||||
return baseCompile(`<div>${content}</div>`, {
|
||||
mode: 'module',
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
}).code
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@ describe('compiler: v-memo transform', () => {
|
|||
expect(
|
||||
baseCompile(`<div v-memo="[x]"></div>`, {
|
||||
mode: 'module',
|
||||
prefixIdentifiers: true
|
||||
}).code
|
||||
prefixIdentifiers: true,
|
||||
}).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -29,8 +29,8 @@ describe('compiler: v-memo transform', () => {
|
|||
expect(
|
||||
compile(
|
||||
`<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()
|
||||
})
|
||||
|
||||
|
@ -39,8 +39,8 @@ describe('compiler: v-memo transform', () => {
|
|||
compile(
|
||||
`<div v-for="{ x, y } in list" :key="x" v-memo="[x, y === z]">
|
||||
<span>foobar</span>
|
||||
</div>`
|
||||
)
|
||||
</div>`,
|
||||
),
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -49,8 +49,8 @@ describe('compiler: v-memo transform', () => {
|
|||
compile(
|
||||
`<template v-for="{ x, y } in list" :key="x" v-memo="[x, y === z]">
|
||||
<span>foobar</span>
|
||||
</template>`
|
||||
)
|
||||
</template>`,
|
||||
),
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import {
|
||||
BindingTypes,
|
||||
type CompilerOptions,
|
||||
type ComponentNode,
|
||||
type ElementNode,
|
||||
type ForNode,
|
||||
NORMALIZE_PROPS,
|
||||
NodeTypes,
|
||||
type ObjectExpression,
|
||||
type PlainElementNode,
|
||||
type VNodeCall,
|
||||
generate,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
generate,
|
||||
ElementNode,
|
||||
ObjectExpression,
|
||||
CompilerOptions,
|
||||
ForNode,
|
||||
PlainElementNode,
|
||||
ComponentNode,
|
||||
NodeTypes,
|
||||
VNodeCall,
|
||||
NORMALIZE_PROPS,
|
||||
BindingTypes
|
||||
} from '../../src'
|
||||
import { ErrorCodes } from '../../src/errors'
|
||||
import { transformModel } from '../../src/transforms/vModel'
|
||||
|
@ -19,7 +19,7 @@ import { transformElement } from '../../src/transforms/transformElement'
|
|||
import { transformExpression } from '../../src/transforms/transformExpression'
|
||||
import { transformFor } from '../../src/transforms/vFor'
|
||||
import { trackSlotScopes } from '../../src/transforms/vSlot'
|
||||
import { CallExpression } from '@babel/types'
|
||||
import type { CallExpression } from '@babel/types'
|
||||
|
||||
function parseWithVModel(template: string, options: CompilerOptions = {}) {
|
||||
const ast = parse(template)
|
||||
|
@ -29,13 +29,13 @@ function parseWithVModel(template: string, options: CompilerOptions = {}) {
|
|||
transformFor,
|
||||
transformExpression,
|
||||
transformElement,
|
||||
trackSlotScopes
|
||||
trackSlotScopes,
|
||||
],
|
||||
directiveTransforms: {
|
||||
...options.directiveTransforms,
|
||||
model: transformModel
|
||||
model: transformModel,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
|
||||
return ast
|
||||
|
@ -51,29 +51,29 @@ describe('compiler: transform v-model', () => {
|
|||
expect(props[0]).toMatchObject({
|
||||
key: {
|
||||
content: 'modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: 'model',
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(props[1]).toMatchObject({
|
||||
key: {
|
||||
content: 'onUpdate:modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
'$event => ((',
|
||||
{
|
||||
content: 'model',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
@ -81,7 +81,7 @@ describe('compiler: transform v-model', () => {
|
|||
|
||||
test('simple expression (with prefixIdentifiers)', () => {
|
||||
const root = parseWithVModel('<input v-model="model" />', {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
const node = root.children[0] as ElementNode
|
||||
const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)
|
||||
|
@ -90,29 +90,29 @@ describe('compiler: transform v-model', () => {
|
|||
expect(props[0]).toMatchObject({
|
||||
key: {
|
||||
content: 'modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: '_ctx.model',
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(props[1]).toMatchObject({
|
||||
key: {
|
||||
content: 'onUpdate:modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
'$event => ((',
|
||||
{
|
||||
content: '_ctx.model',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
||||
|
@ -128,29 +128,29 @@ describe('compiler: transform v-model', () => {
|
|||
expect(props[0]).toMatchObject({
|
||||
key: {
|
||||
content: 'modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: '\n model\n.\nfoo \n',
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(props[1]).toMatchObject({
|
||||
key: {
|
||||
content: 'onUpdate:modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
'$event => ((',
|
||||
{
|
||||
content: '\n model\n.\nfoo \n',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
@ -165,29 +165,29 @@ describe('compiler: transform v-model', () => {
|
|||
expect(props[0]).toMatchObject({
|
||||
key: {
|
||||
content: 'modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: 'model[index]',
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(props[1]).toMatchObject({
|
||||
key: {
|
||||
content: 'onUpdate:modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
'$event => ((',
|
||||
{
|
||||
content: 'model[index]',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
@ -195,7 +195,7 @@ describe('compiler: transform v-model', () => {
|
|||
|
||||
test('compound expression (with prefixIdentifiers)', () => {
|
||||
const root = parseWithVModel('<input v-model="model[index]" />', {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
const node = root.children[0] as ElementNode
|
||||
const props = ((node.codegenNode as VNodeCall).props as ObjectExpression)
|
||||
|
@ -204,28 +204,28 @@ describe('compiler: transform v-model', () => {
|
|||
expect(props[0]).toMatchObject({
|
||||
key: {
|
||||
content: 'modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
{
|
||||
content: '_ctx.model',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
'[',
|
||||
{
|
||||
content: '_ctx.index',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
']'
|
||||
]
|
||||
}
|
||||
']',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
expect(props[1]).toMatchObject({
|
||||
key: {
|
||||
content: 'onUpdate:modelValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
|
@ -234,19 +234,19 @@ describe('compiler: transform v-model', () => {
|
|||
children: [
|
||||
{
|
||||
content: '_ctx.model',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
'[',
|
||||
{
|
||||
content: '_ctx.index',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
']'
|
||||
]
|
||||
']',
|
||||
],
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
||||
|
@ -260,29 +260,29 @@ describe('compiler: transform v-model', () => {
|
|||
expect(props[0]).toMatchObject({
|
||||
key: {
|
||||
content: 'foo-value',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
content: 'model',
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
|
||||
expect(props[1]).toMatchObject({
|
||||
key: {
|
||||
content: 'onUpdate:fooValue',
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
'$event => ((',
|
||||
{
|
||||
content: 'model',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
@ -304,12 +304,12 @@ describe('compiler: transform v-model', () => {
|
|||
{
|
||||
key: {
|
||||
content: 'value',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
value: {
|
||||
content: 'model',
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: {
|
||||
|
@ -317,24 +317,24 @@ describe('compiler: transform v-model', () => {
|
|||
'"onUpdate:" + ',
|
||||
{
|
||||
content: 'value',
|
||||
isStatic: false
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
'$event => ((',
|
||||
{
|
||||
content: 'model',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
@ -342,7 +342,7 @@ describe('compiler: transform v-model', () => {
|
|||
|
||||
test('with dynamic argument (with prefixIdentifiers)', () => {
|
||||
const root = parseWithVModel('<input v-model:[value]="model" />', {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
const node = root.children[0] as ElementNode
|
||||
const props = (node.codegenNode as VNodeCall)
|
||||
|
@ -358,12 +358,12 @@ describe('compiler: transform v-model', () => {
|
|||
{
|
||||
key: {
|
||||
content: '_ctx.value',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
value: {
|
||||
content: '_ctx.model',
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: {
|
||||
|
@ -371,24 +371,24 @@ describe('compiler: transform v-model', () => {
|
|||
'"onUpdate:" + ',
|
||||
{
|
||||
content: '_ctx.value',
|
||||
isStatic: false
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
value: {
|
||||
children: [
|
||||
'$event => ((',
|
||||
{
|
||||
content: '_ctx.model',
|
||||
isStatic: false
|
||||
isStatic: false,
|
||||
},
|
||||
') = $event)'
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
') = $event)',
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
expect(generate(root, { mode: 'module' }).code).toMatchSnapshot()
|
||||
|
@ -397,7 +397,7 @@ describe('compiler: transform v-model', () => {
|
|||
test('should cache update handler w/ cacheHandlers: true', () => {
|
||||
const root = parseWithVModel('<input v-model="foo" />', {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
expect(root.cached).toBe(1)
|
||||
const codegen = (root.children[0] as PlainElementNode)
|
||||
|
@ -405,7 +405,7 @@ describe('compiler: transform v-model', () => {
|
|||
// should not list cached prop in dynamicProps
|
||||
expect(codegen.dynamicProps).toBe(`["modelValue"]`)
|
||||
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]" />',
|
||||
{
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
}
|
||||
cacheHandlers: true,
|
||||
},
|
||||
)
|
||||
expect(root.cached).toBe(0)
|
||||
const codegen = (
|
||||
|
@ -423,14 +423,14 @@ describe('compiler: transform v-model', () => {
|
|||
).codegenNode as VNodeCall
|
||||
expect(codegen.dynamicProps).toBe(`["modelValue", "onUpdate:modelValue"]`)
|
||||
expect(
|
||||
(codegen.props as ObjectExpression).properties[1].value.type
|
||||
(codegen.props as ObjectExpression).properties[1].value.type,
|
||||
).not.toBe(NodeTypes.JS_CACHE_EXPRESSION)
|
||||
})
|
||||
|
||||
test('should not cache update handler if it inside v-once', () => {
|
||||
const root = parseWithVModel('<div v-once><input v-model="foo" /></div>', {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
expect(root.cached).not.toBe(2)
|
||||
expect(root.cached).toBe(1)
|
||||
|
@ -440,8 +440,8 @@ describe('compiler: transform v-model', () => {
|
|||
const root = parseWithVModel(
|
||||
'<Comp v-slot="{ foo }"><input v-model="foo.bar"/></Comp>',
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
const codegen = (
|
||||
(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', () => {
|
||||
const root = parseWithVModel('<Comp v-model.trim.bar-baz="foo" />', {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
const vnodeCall = (root.children[0] as ComponentNode)
|
||||
.codegenNode as VNodeCall
|
||||
|
@ -462,9 +462,12 @@ describe('compiler: transform v-model', () => {
|
|||
{ key: { content: `onUpdate:modelValue` } },
|
||||
{
|
||||
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
|
||||
// gonna change
|
||||
|
@ -475,8 +478,8 @@ describe('compiler: transform v-model', () => {
|
|||
const root = parseWithVModel(
|
||||
'<Comp v-model:foo.trim="foo" v-model:bar.number="bar" />',
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
const vnodeCall = (root.children[0] as ComponentNode)
|
||||
.codegenNode as VNodeCall
|
||||
|
@ -487,20 +490,20 @@ describe('compiler: transform v-model', () => {
|
|||
{ key: { content: `onUpdate:foo` } },
|
||||
{
|
||||
key: { content: 'fooModifiers' },
|
||||
value: { content: `{ trim: true }`, isStatic: false }
|
||||
value: { content: `{ trim: true }`, isStatic: false },
|
||||
},
|
||||
{ key: { content: `bar` } },
|
||||
{ key: { content: `onUpdate:bar` } },
|
||||
{
|
||||
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
|
||||
// gonna change
|
||||
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).toHaveBeenCalledWith(
|
||||
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).toHaveBeenCalledWith(
|
||||
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).toHaveBeenCalledWith(
|
||||
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()
|
||||
parseWithVModel('<span v-for="i in list" v-model="i" />', {
|
||||
onError,
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
|
||||
expect(onError).toHaveBeenCalledTimes(1)
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
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" />', {
|
||||
onError,
|
||||
bindingMetadata: {
|
||||
p: BindingTypes.PROPS
|
||||
}
|
||||
p: BindingTypes.PROPS,
|
||||
},
|
||||
})
|
||||
|
||||
expect(onError).toHaveBeenCalledTimes(1)
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
code: ErrorCodes.X_V_MODEL_ON_PROPS
|
||||
})
|
||||
code: ErrorCodes.X_V_MODEL_ON_PROPS,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
baseParse as parse,
|
||||
CompilerOptions,
|
||||
ElementNode,
|
||||
type CompilerOptions,
|
||||
type ElementNode,
|
||||
ErrorCodes,
|
||||
TO_HANDLER_KEY,
|
||||
helperNameMap,
|
||||
NodeTypes,
|
||||
ObjectExpression,
|
||||
type ObjectExpression,
|
||||
TO_HANDLER_KEY,
|
||||
type VNodeCall,
|
||||
helperNameMap,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
VNodeCall
|
||||
} from '../../src'
|
||||
import { transformOn } from '../../src/transforms/vOn'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
|
@ -19,13 +19,13 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) {
|
|||
transform(ast, {
|
||||
nodeTransforms: [transformExpression, transformElement],
|
||||
directiveTransforms: {
|
||||
on: transformOn
|
||||
on: transformOn,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return {
|
||||
root: ast,
|
||||
node: ast.children[0] as ElementNode
|
||||
node: ast.children[0] as ElementNode,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,13 +41,13 @@ describe('compiler: transform v-on', () => {
|
|||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 11
|
||||
column: 11,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 16
|
||||
}
|
||||
}
|
||||
column: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
value: {
|
||||
content: `onClick`,
|
||||
|
@ -55,16 +55,16 @@ describe('compiler: transform v-on', () => {
|
|||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 18
|
||||
column: 18,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 25
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
column: 25,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -78,22 +78,22 @@ describe('compiler: transform v-on', () => {
|
|||
children: [
|
||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||
{ content: `event` },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `handler`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('dynamic arg with prefixing', () => {
|
||||
const { node } = parseWithVOn(`<div v-on:[event]="handler"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -103,22 +103,22 @@ describe('compiler: transform v-on', () => {
|
|||
children: [
|
||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||
{ content: `_ctx.event` },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.handler`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('dynamic arg with complex exp prefixing', () => {
|
||||
const { node } = parseWithVOn(`<div v-on:[event(foo)]="handler"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -131,16 +131,16 @@ describe('compiler: transform v-on', () => {
|
|||
`(`,
|
||||
{ content: `_ctx.foo` },
|
||||
`)`,
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `_ctx.handler`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -152,10 +152,10 @@ describe('compiler: transform v-on', () => {
|
|||
key: { content: `onClick` },
|
||||
value: {
|
||||
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
|
||||
// in this case the return value is discarded and the behavior is
|
||||
// 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
|
||||
// in this case the return value is discarded and the behavior is
|
||||
// consistent with 2.x
|
||||
children: [`$event => {`, { content: `\nfoo();\nbar()\n` }, `}`]
|
||||
}
|
||||
}
|
||||
]
|
||||
children: [`$event => {`, { content: `\nfoo();\nbar()\n` }, `}`],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('inline statement w/ prefixIdentifiers: true', () => {
|
||||
const { node } = parseWithVOn(`<div @click="foo($event)"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -214,20 +214,20 @@ describe('compiler: transform v-on', () => {
|
|||
`(`,
|
||||
// should NOT prefix $event
|
||||
{ content: `$event` },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
`)`
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('multiple inline statements w/ prefixIdentifiers: true', () => {
|
||||
const { node } = parseWithVOn(`<div @click="foo($event);bar()"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -245,14 +245,14 @@ describe('compiler: transform v-on', () => {
|
|||
{ content: `$event` },
|
||||
`);`,
|
||||
{ content: `_ctx.bar` },
|
||||
`()`
|
||||
]
|
||||
`()`,
|
||||
],
|
||||
},
|
||||
`}`
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
`}`,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -264,10 +264,10 @@ describe('compiler: transform v-on', () => {
|
|||
key: { content: `onClick` },
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `$event => foo($event)`
|
||||
}
|
||||
}
|
||||
]
|
||||
content: `$event => foo($event)`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -279,10 +279,10 @@ describe('compiler: transform v-on', () => {
|
|||
key: { content: `onClick` },
|
||||
value: {
|
||||
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 => {
|
||||
foo($event)
|
||||
}
|
||||
"/>`
|
||||
"/>`,
|
||||
)
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -304,10 +304,10 @@ describe('compiler: transform v-on', () => {
|
|||
$event => {
|
||||
foo($event)
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
]
|
||||
`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -317,7 +317,7 @@ describe('compiler: transform v-on', () => {
|
|||
function($event) {
|
||||
foo($event)
|
||||
}
|
||||
"/>`
|
||||
"/>`,
|
||||
)
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -329,10 +329,10 @@ describe('compiler: transform v-on', () => {
|
|||
function($event) {
|
||||
foo($event)
|
||||
}
|
||||
`
|
||||
}
|
||||
}
|
||||
]
|
||||
`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -344,16 +344,16 @@ describe('compiler: transform v-on', () => {
|
|||
key: { content: `onClick` },
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `a['b' + c]`
|
||||
}
|
||||
}
|
||||
]
|
||||
content: `a['b' + c]`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('complex member expression w/ prefixIdentifiers: true', () => {
|
||||
const { node } = parseWithVOn(`<div @click="a['b' + c]"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -365,17 +365,17 @@ describe('compiler: transform v-on', () => {
|
|||
{ content: `_ctx.a` },
|
||||
`['b' + `,
|
||||
{ content: `_ctx.c` },
|
||||
`]`
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
`]`,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('function expression w/ prefixIdentifiers: true', () => {
|
||||
const { node } = parseWithVOn(`<div @click="e => foo(e)"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
properties: [
|
||||
|
@ -389,11 +389,11 @@ describe('compiler: transform v-on', () => {
|
|||
{ content: `_ctx.foo` },
|
||||
`(`,
|
||||
{ content: `e` },
|
||||
`)`
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -405,13 +405,13 @@ describe('compiler: transform v-on', () => {
|
|||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 6
|
||||
column: 6,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 16
|
||||
}
|
||||
}
|
||||
column: 16,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -427,13 +427,13 @@ describe('compiler: transform v-on', () => {
|
|||
properties: [
|
||||
{
|
||||
key: {
|
||||
content: `onFooBar`
|
||||
content: `onFooBar`,
|
||||
},
|
||||
value: {
|
||||
content: `onMount`
|
||||
}
|
||||
}
|
||||
]
|
||||
content: `onMount`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -445,39 +445,39 @@ describe('compiler: transform v-on', () => {
|
|||
loc: {
|
||||
start: {
|
||||
line: 1,
|
||||
column: 11
|
||||
column: 11,
|
||||
},
|
||||
end: {
|
||||
line: 1,
|
||||
column: 24
|
||||
}
|
||||
}
|
||||
column: 24,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('vue: prefixed events', () => {
|
||||
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({
|
||||
properties: [
|
||||
{
|
||||
key: {
|
||||
content: `onVnodeMounted`
|
||||
content: `onVnodeMounted`,
|
||||
},
|
||||
value: {
|
||||
content: `onMount`
|
||||
}
|
||||
content: `onMount`,
|
||||
},
|
||||
},
|
||||
{
|
||||
key: {
|
||||
content: `onVnodeBeforeUpdate`
|
||||
content: `onVnodeBeforeUpdate`,
|
||||
},
|
||||
value: {
|
||||
content: `onBeforeUpdate`
|
||||
}
|
||||
}
|
||||
]
|
||||
content: `onBeforeUpdate`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -485,35 +485,35 @@ describe('compiler: transform v-on', () => {
|
|||
test('empty handler', () => {
|
||||
const { root, node } = parseWithVOn(`<div v-on:click.prevent />`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
expect(root.cached).toBe(1)
|
||||
const vnodeCall = node.codegenNode as VNodeCall
|
||||
// should not treat cached handler as dynamicProp, so no flags
|
||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||
expect(
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `() => {}`
|
||||
}
|
||||
content: `() => {}`,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('member expression handler', () => {
|
||||
const { root, node } = parseWithVOn(`<div v-on:click="foo" />`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
expect(root.cached).toBe(1)
|
||||
const vnodeCall = node.codegenNode as VNodeCall
|
||||
// should not treat cached handler as dynamicProp, so no flags
|
||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||
expect(
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
|
@ -522,23 +522,23 @@ describe('compiler: transform v-on', () => {
|
|||
children: [
|
||||
`(...args) => (`,
|
||||
{ content: `_ctx.foo && _ctx.foo(...args)` },
|
||||
`)`
|
||||
]
|
||||
}
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('compound member expression handler', () => {
|
||||
const { root, node } = parseWithVOn(`<div v-on:click="foo.bar" />`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
expect(root.cached).toBe(1)
|
||||
const vnodeCall = node.codegenNode as VNodeCall
|
||||
// should not treat cached handler as dynamicProp, so no flags
|
||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||
expect(
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
|
@ -555,12 +555,12 @@ describe('compiler: transform v-on', () => {
|
|||
{ content: `_ctx.foo` },
|
||||
`.`,
|
||||
{ content: `bar` },
|
||||
`(...args)`
|
||||
]
|
||||
`(...args)`,
|
||||
],
|
||||
},
|
||||
`)`
|
||||
]
|
||||
}
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -568,7 +568,7 @@ describe('compiler: transform v-on', () => {
|
|||
const { root } = parseWithVOn(`<comp v-on:click="foo" />`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true,
|
||||
isNativeTag: tag => tag === 'div'
|
||||
isNativeTag: tag => tag === 'div',
|
||||
})
|
||||
expect(root.cached).toBe(0)
|
||||
})
|
||||
|
@ -578,8 +578,8 @@ describe('compiler: transform v-on', () => {
|
|||
`<div v-once><div v-on:click="foo"/></div>`,
|
||||
{
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
}
|
||||
cacheHandlers: true,
|
||||
},
|
||||
)
|
||||
expect(root.cached).not.toBe(2)
|
||||
expect(root.cached).toBe(1)
|
||||
|
@ -588,21 +588,21 @@ describe('compiler: transform v-on', () => {
|
|||
test('inline function expression handler', () => {
|
||||
const { root, node } = parseWithVOn(`<div v-on:click="() => foo()" />`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
expect(root.cached).toBe(1)
|
||||
const vnodeCall = node.codegenNode as VNodeCall
|
||||
// should not treat cached handler as dynamicProp, so no flags
|
||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||
expect(
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
value: {
|
||||
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()" />`,
|
||||
{
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
}
|
||||
cacheHandlers: true,
|
||||
},
|
||||
)
|
||||
expect(root.cached).toBe(1)
|
||||
const vnodeCall = node.codegenNode as VNodeCall
|
||||
// should not treat cached handler as dynamicProp, so no flags
|
||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||
expect(
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
value: {
|
||||
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() } " />`,
|
||||
{
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
}
|
||||
cacheHandlers: true,
|
||||
},
|
||||
)
|
||||
expect(root.cached).toBe(1)
|
||||
const vnodeCall = node.codegenNode as VNodeCall
|
||||
// should not treat cached handler as dynamicProp, so no flags
|
||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||
expect(
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
|
@ -652,16 +652,16 @@ describe('compiler: transform v-on', () => {
|
|||
children: [
|
||||
`async function () { await `,
|
||||
{ content: `_ctx.foo` },
|
||||
`() } `
|
||||
]
|
||||
}
|
||||
`() } `,
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('inline statement handler', () => {
|
||||
const { root, node } = parseWithVOn(`<div v-on:click="foo++" />`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
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
|
||||
expect(vnodeCall.patchFlag).toBeUndefined()
|
||||
expect(
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value
|
||||
(vnodeCall.props as ObjectExpression).properties[0].value,
|
||||
).toMatchObject({
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
|
@ -678,9 +678,9 @@ describe('compiler: transform v-on', () => {
|
|||
children: [
|
||||
`$event => (`,
|
||||
{ children: [{ content: `_ctx.foo` }, `++`] },
|
||||
`)`
|
||||
]
|
||||
}
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {
|
||||
baseParse as parse,
|
||||
transform,
|
||||
type CompilerOptions,
|
||||
NodeTypes,
|
||||
generate,
|
||||
CompilerOptions,
|
||||
getBaseTransformPreset
|
||||
getBaseTransformPreset,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
} from '../../src'
|
||||
import { RENDER_SLOT, SET_BLOCK_TRACKING } from '../../src/runtimeHelpers'
|
||||
|
||||
|
@ -14,7 +14,7 @@ function transformWithOnce(template: string, options: CompilerOptions = {}) {
|
|||
transform(ast, {
|
||||
nodeTransforms,
|
||||
directiveTransforms,
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ describe('compiler: v-once transform', () => {
|
|||
index: 0,
|
||||
value: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`
|
||||
}
|
||||
tag: `"div"`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -44,8 +44,8 @@ describe('compiler: v-once transform', () => {
|
|||
index: 0,
|
||||
value: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`
|
||||
}
|
||||
tag: `"div"`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -59,8 +59,8 @@ describe('compiler: v-once transform', () => {
|
|||
index: 0,
|
||||
value: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `_component_Comp`
|
||||
}
|
||||
tag: `_component_Comp`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -74,8 +74,8 @@ describe('compiler: v-once transform', () => {
|
|||
index: 0,
|
||||
value: {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: RENDER_SLOT
|
||||
}
|
||||
callee: RENDER_SLOT,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -90,7 +90,7 @@ describe('compiler: v-once transform', () => {
|
|||
// cached nodes should be ignored by hoistStatic transform
|
||||
test('with hoistStatic: true', () => {
|
||||
const root = transformWithOnce(`<div><div v-once /></div>`, {
|
||||
hoistStatic: true
|
||||
hoistStatic: true,
|
||||
})
|
||||
expect(root.cached).toBe(1)
|
||||
expect(root.helpers).toContain(SET_BLOCK_TRACKING)
|
||||
|
@ -100,8 +100,8 @@ describe('compiler: v-once transform', () => {
|
|||
index: 0,
|
||||
value: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`
|
||||
}
|
||||
tag: `"div"`,
|
||||
},
|
||||
})
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -119,14 +119,14 @@ describe('compiler: v-once transform', () => {
|
|||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
consequent: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"div"`
|
||||
tag: `"div"`,
|
||||
},
|
||||
alternate: {
|
||||
type: NodeTypes.VNODE_CALL,
|
||||
tag: `"p"`
|
||||
}
|
||||
}
|
||||
}
|
||||
tag: `"p"`,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -138,8 +138,8 @@ describe('compiler: v-once transform', () => {
|
|||
type: NodeTypes.FOR,
|
||||
// should cache the entire v-for expression, not just a single branch
|
||||
codegenNode: {
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION
|
||||
}
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
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,
|
||||
transform,
|
||||
generate,
|
||||
ElementNode,
|
||||
NodeTypes,
|
||||
ErrorCodes,
|
||||
ForNode,
|
||||
ComponentNode,
|
||||
VNodeCall,
|
||||
SlotsExpression,
|
||||
ObjectExpression,
|
||||
SimpleExpressionNode,
|
||||
RenderSlotCall
|
||||
} from '../../src'
|
||||
import { transformElement } from '../../src/transforms/transformElement'
|
||||
import { transformOn } from '../../src/transforms/vOn'
|
||||
|
@ -21,7 +21,7 @@ import { transformExpression } from '../../src/transforms/transformExpression'
|
|||
import { transformSlotOutlet } from '../../src/transforms/transformSlotOutlet'
|
||||
import {
|
||||
trackSlotScopes,
|
||||
trackVForSlotScopes
|
||||
trackVForSlotScopes,
|
||||
} from '../../src/transforms/vSlot'
|
||||
import { CREATE_SLOTS, RENDER_LIST } from '../../src/runtimeHelpers'
|
||||
import { createObjectMatcher, genFlagText } from '../testUtils'
|
||||
|
@ -31,7 +31,7 @@ import { transformIf } from '../../src/transforms/vIf'
|
|||
|
||||
function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
||||
const ast = parse(template, {
|
||||
whitespace: options.whitespace
|
||||
whitespace: options.whitespace,
|
||||
})
|
||||
transform(ast, {
|
||||
nodeTransforms: [
|
||||
|
@ -42,13 +42,13 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
|||
: []),
|
||||
transformSlotOutlet,
|
||||
transformElement,
|
||||
trackSlotScopes
|
||||
trackSlotScopes,
|
||||
],
|
||||
directiveTransforms: {
|
||||
on: transformOn,
|
||||
bind: transformBind
|
||||
bind: transformBind,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return {
|
||||
root: ast,
|
||||
|
@ -56,7 +56,7 @@ function parseWithSlots(template: string, options: CompilerOptions = {}) {
|
|||
ast.children[0].type === NodeTypes.ELEMENT
|
||||
? ((ast.children[0].codegenNode as VNodeCall)
|
||||
.children as SlotsExpression)
|
||||
: null
|
||||
: null,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,25 +70,25 @@ function createSlotMatcher(obj: Record<string, any>, isDynamic = false) {
|
|||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
isStatic: !/^\[/.test(key),
|
||||
content: key.replace(/^\[|\]$/g, '')
|
||||
content: key.replace(/^\[|\]$/g, ''),
|
||||
},
|
||||
value: obj[key]
|
||||
value: obj[key],
|
||||
} as any
|
||||
})
|
||||
.concat({
|
||||
key: { content: `_` },
|
||||
value: {
|
||||
content: isDynamic ? `2 /* DYNAMIC */` : `1 /* STABLE */`,
|
||||
isStatic: false
|
||||
}
|
||||
})
|
||||
isStatic: false,
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
describe('compiler: transform component slots', () => {
|
||||
test('implicit default slot', () => {
|
||||
const { root, slots } = parseWithSlots(`<Comp><div/></Comp>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher({
|
||||
|
@ -98,11 +98,11 @@ describe('compiler: transform component slots', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: `div`
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
tag: `div`,
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -110,7 +110,7 @@ describe('compiler: transform component slots', () => {
|
|||
test('on-component default slot', () => {
|
||||
const { root, slots } = parseWithSlots(
|
||||
`<Comp v-slot="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher({
|
||||
|
@ -118,24 +118,24 @@ describe('compiler: transform component slots', () => {
|
|||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `foo` }, ` }`]
|
||||
children: [`{ `, { content: `foo` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.bar`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
content: `_ctx.bar`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -143,7 +143,7 @@ describe('compiler: transform component slots', () => {
|
|||
test('on component named slot', () => {
|
||||
const { root, slots } = parseWithSlots(
|
||||
`<Comp v-slot:named="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher({
|
||||
|
@ -151,24 +151,24 @@ describe('compiler: transform component slots', () => {
|
|||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `foo` }, ` }`]
|
||||
children: [`{ `, { content: `foo` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.bar`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
content: `_ctx.bar`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -183,7 +183,7 @@ describe('compiler: transform component slots', () => {
|
|||
{{ foo }}{{ bar }}
|
||||
</template>
|
||||
</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher({
|
||||
|
@ -191,45 +191,45 @@ describe('compiler: transform component slots', () => {
|
|||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `foo` }, ` }`]
|
||||
children: [`{ `, { content: `foo` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.bar`
|
||||
}
|
||||
}
|
||||
]
|
||||
content: `_ctx.bar`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
two: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `bar` }, ` }`]
|
||||
children: [`{ `, { content: `bar` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.foo`
|
||||
}
|
||||
content: `_ctx.foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `bar`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
content: `bar`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -237,7 +237,7 @@ describe('compiler: transform component slots', () => {
|
|||
test('on component dynamically named slot', () => {
|
||||
const { root, slots } = parseWithSlots(
|
||||
`<Comp v-slot:[named]="{ foo }">{{ foo }}{{ bar }}</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher(
|
||||
|
@ -246,26 +246,26 @@ describe('compiler: transform component slots', () => {
|
|||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `foo` }, ` }`]
|
||||
children: [`{ `, { content: `foo` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.bar`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
content: `_ctx.bar`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
true
|
||||
)
|
||||
true,
|
||||
),
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -274,7 +274,7 @@ describe('compiler: transform component slots', () => {
|
|||
const { root, slots } = parseWithSlots(
|
||||
`<Comp>
|
||||
<template #one>foo</template>bar<span/>
|
||||
</Comp>`
|
||||
</Comp>`,
|
||||
)
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher({
|
||||
|
@ -284,9 +284,9 @@ describe('compiler: transform component slots', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `foo`
|
||||
}
|
||||
]
|
||||
content: `foo`,
|
||||
},
|
||||
],
|
||||
},
|
||||
default: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
|
@ -294,15 +294,15 @@ describe('compiler: transform component slots', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `bar`
|
||||
content: `bar`,
|
||||
},
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: `span`
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
tag: `span`,
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -317,7 +317,7 @@ describe('compiler: transform component slots', () => {
|
|||
{{ foo }}{{ bar }}
|
||||
</template>
|
||||
</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher(
|
||||
|
@ -326,47 +326,47 @@ describe('compiler: transform component slots', () => {
|
|||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `foo` }, ` }`]
|
||||
children: [`{ `, { content: `foo` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.bar`
|
||||
}
|
||||
}
|
||||
]
|
||||
content: `_ctx.bar`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
'[_ctx.two]': {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `bar` }, ` }`]
|
||||
children: [`{ `, { content: `bar` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.foo`
|
||||
}
|
||||
content: `_ctx.foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `bar`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
content: `bar`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
true
|
||||
)
|
||||
true,
|
||||
),
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -381,7 +381,7 @@ describe('compiler: transform component slots', () => {
|
|||
{{ foo }}{{ bar }}{{ baz }}
|
||||
</template>
|
||||
</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject(
|
||||
createSlotMatcher({
|
||||
|
@ -389,7 +389,7 @@ describe('compiler: transform component slots', () => {
|
|||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `foo` }, ` }`]
|
||||
children: [`{ `, { content: `foo` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
|
@ -404,63 +404,63 @@ describe('compiler: transform component slots', () => {
|
|||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
children: [`{ `, { content: `bar` }, ` }`]
|
||||
children: [`{ `, { content: `bar` }, ` }`],
|
||||
},
|
||||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `bar`
|
||||
}
|
||||
content: `bar`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.baz`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
content: `_ctx.baz`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
true
|
||||
true,
|
||||
),
|
||||
// nested slot should be forced dynamic, since scope variables
|
||||
// are not tracked as dependencies of the slot.
|
||||
patchFlag: genFlagText(PatchFlags.DYNAMIC_SLOTS)
|
||||
}
|
||||
patchFlag: genFlagText(PatchFlags.DYNAMIC_SLOTS),
|
||||
},
|
||||
},
|
||||
// test scope
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: ` `
|
||||
content: ` `,
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `foo`
|
||||
}
|
||||
content: `foo`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.bar`
|
||||
}
|
||||
content: `_ctx.bar`,
|
||||
},
|
||||
},
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: {
|
||||
content: `_ctx.baz`
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
content: `_ctx.baz`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -469,13 +469,13 @@ describe('compiler: transform component slots', () => {
|
|||
const { root } = parseWithSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar">foo</Comp>
|
||||
</div>`
|
||||
</div>`,
|
||||
)
|
||||
const div = ((root.children[0] as ForNode).children[0] as ElementNode)
|
||||
.codegenNode as any
|
||||
const comp = div.children[0]
|
||||
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">
|
||||
<Comp v-slot="bar">foo</Comp>
|
||||
</div>`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar">{{ i }}</Comp>
|
||||
</div>`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
|
||||
// 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="bar">{{ bar }}</Comp>
|
||||
</Comp>`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<Comp v-slot="foo">
|
||||
<Comp v-slot="bar">{{ foo }}</Comp>
|
||||
</Comp>`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
|
||||
// #2564
|
||||
|
@ -534,14 +534,14 @@ describe('compiler: transform component slots', () => {
|
|||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar"><button @click="fn(i)" /></Comp>
|
||||
</div>`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
|
||||
assertDynamicSlots(
|
||||
`<div v-for="i in list">
|
||||
<Comp v-slot="bar"><button @click="fn()" /></Comp>
|
||||
</div>`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -549,14 +549,14 @@ describe('compiler: transform component slots', () => {
|
|||
const { root, slots } = parseWithSlots(
|
||||
`<Comp>
|
||||
<template #one v-if="ok">hello</template>
|
||||
</Comp>`
|
||||
</Comp>`,
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
_: `[2 /* DYNAMIC */]`
|
||||
_: `[2 /* DYNAMIC */]`,
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
|
@ -568,21 +568,21 @@ describe('compiler: transform component slots', () => {
|
|||
name: `one`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
returns: [{ type: NodeTypes.TEXT, content: `hello` }]
|
||||
returns: [{ type: NodeTypes.TEXT, content: `hello` }],
|
||||
},
|
||||
key: `0`
|
||||
key: `0`,
|
||||
}),
|
||||
alternate: {
|
||||
content: `undefined`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
PatchFlags.DYNAMIC_SLOTS + '',
|
||||
)
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -592,14 +592,14 @@ describe('compiler: transform component slots', () => {
|
|||
`<Comp>
|
||||
<template #one="props" v-if="ok">{{ props }}</template>
|
||||
</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
_: `[2 /* DYNAMIC */]`
|
||||
_: `[2 /* DYNAMIC */]`,
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
|
@ -615,23 +615,23 @@ describe('compiler: transform component slots', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: { content: `props` }
|
||||
}
|
||||
]
|
||||
content: { content: `props` },
|
||||
},
|
||||
],
|
||||
},
|
||||
key: `0`
|
||||
key: `0`,
|
||||
}),
|
||||
alternate: {
|
||||
content: `undefined`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
PatchFlags.DYNAMIC_SLOTS + '',
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -642,14 +642,14 @@ describe('compiler: transform component slots', () => {
|
|||
<template #one v-if="ok">foo</template>
|
||||
<template #two="props" v-else-if="orNot">bar</template>
|
||||
<template #one v-else>baz</template>
|
||||
</Comp>`
|
||||
</Comp>`,
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
_: `[2 /* DYNAMIC */]`
|
||||
_: `[2 /* DYNAMIC */]`,
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
|
@ -662,9 +662,9 @@ describe('compiler: transform component slots', () => {
|
|||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: undefined,
|
||||
returns: [{ type: NodeTypes.TEXT, content: `foo` }]
|
||||
returns: [{ type: NodeTypes.TEXT, content: `foo` }],
|
||||
},
|
||||
key: `0`
|
||||
key: `0`,
|
||||
}),
|
||||
alternate: {
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
|
@ -674,27 +674,27 @@ describe('compiler: transform component slots', () => {
|
|||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
params: { content: `props` },
|
||||
returns: [{ type: NodeTypes.TEXT, content: `bar` }]
|
||||
returns: [{ type: NodeTypes.TEXT, content: `bar` }],
|
||||
},
|
||||
key: `1`
|
||||
key: `1`,
|
||||
}),
|
||||
alternate: createObjectMatcher({
|
||||
name: `one`,
|
||||
fn: {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
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(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
PatchFlags.DYNAMIC_SLOTS + '',
|
||||
)
|
||||
expect(generate(root).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -704,14 +704,14 @@ describe('compiler: transform component slots', () => {
|
|||
`<Comp>
|
||||
<template v-for="name in list" #[name]>{{ name }}</template>
|
||||
</Comp>`,
|
||||
{ prefixIdentifiers: true }
|
||||
{ prefixIdentifiers: true },
|
||||
)
|
||||
expect(slots).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
callee: CREATE_SLOTS,
|
||||
arguments: [
|
||||
createObjectMatcher({
|
||||
_: `[2 /* DYNAMIC */]`
|
||||
_: `[2 /* DYNAMIC */]`,
|
||||
}),
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
|
@ -731,20 +731,20 @@ describe('compiler: transform component slots', () => {
|
|||
returns: [
|
||||
{
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
content: { content: `name`, isStatic: false }
|
||||
}
|
||||
]
|
||||
}
|
||||
})
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
content: { content: `name`, isStatic: false },
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
})
|
||||
expect((root as any).children[0].codegenNode.patchFlag).toMatch(
|
||||
PatchFlags.DYNAMIC_SLOTS + ''
|
||||
PatchFlags.DYNAMIC_SLOTS + '',
|
||||
)
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -755,13 +755,13 @@ describe('compiler: transform component slots', () => {
|
|||
properties: [
|
||||
{
|
||||
key: { content: `default` },
|
||||
value: { type: NodeTypes.JS_FUNCTION_EXPRESSION }
|
||||
value: { type: NodeTypes.JS_FUNCTION_EXPRESSION },
|
||||
},
|
||||
{
|
||||
key: { content: `_` },
|
||||
value: { content: `3 /* FORWARDED */` }
|
||||
}
|
||||
]
|
||||
value: { content: `3 /* FORWARDED */` },
|
||||
},
|
||||
],
|
||||
}
|
||||
test('<slot> tag only', () => {
|
||||
const { slots } = parseWithSlots(`<Comp><slot/></Comp>`)
|
||||
|
@ -780,7 +780,7 @@ describe('compiler: transform component slots', () => {
|
|||
|
||||
test('<slot> tag w/ template', () => {
|
||||
const { slots } = parseWithSlots(
|
||||
`<Comp><template #default><slot/></template></Comp>`
|
||||
`<Comp><template #default><slot/></template></Comp>`,
|
||||
)
|
||||
expect(slots).toMatchObject(toMatch)
|
||||
})
|
||||
|
@ -793,7 +793,7 @@ describe('compiler: transform component slots', () => {
|
|||
// # fix: #6900
|
||||
test('consistent behavior of @xxx:modelValue and @xxx:model-value', () => {
|
||||
const { root: rootUpper } = parseWithSlots(
|
||||
`<div><slot @foo:modelValue="handler" /></div>`
|
||||
`<div><slot @foo:modelValue="handler" /></div>`,
|
||||
)
|
||||
const slotNodeUpper = (rootUpper.codegenNode! as VNodeCall)
|
||||
.children as ElementNode[]
|
||||
|
@ -805,19 +805,19 @@ describe('compiler: transform component slots', () => {
|
|||
{
|
||||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'onFoo:modelValue'
|
||||
content: 'onFoo:modelValue',
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `handler`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const { root } = parseWithSlots(
|
||||
`<div><slot @foo:model-Value="handler" /></div>`
|
||||
`<div><slot @foo:model-Value="handler" /></div>`,
|
||||
)
|
||||
const slotNode = (root.codegenNode! as VNodeCall)
|
||||
.children as ElementNode[]
|
||||
|
@ -828,15 +828,15 @@ describe('compiler: transform component slots', () => {
|
|||
{
|
||||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: 'onFoo:modelValue'
|
||||
content: 'onFoo:modelValue',
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `handler`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -853,14 +853,14 @@ describe('compiler: transform component slots', () => {
|
|||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
column: index + 1,
|
||||
},
|
||||
end: {
|
||||
offset: index + 3,
|
||||
line: 1,
|
||||
column: index + 4
|
||||
}
|
||||
}
|
||||
column: index + 4,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -875,14 +875,14 @@ describe('compiler: transform component slots', () => {
|
|||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
column: index + 1,
|
||||
},
|
||||
end: {
|
||||
offset: index + 4,
|
||||
line: 1,
|
||||
column: index + 5
|
||||
}
|
||||
}
|
||||
column: index + 5,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -897,14 +897,14 @@ describe('compiler: transform component slots', () => {
|
|||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
column: index + 1,
|
||||
},
|
||||
end: {
|
||||
offset: index + 4,
|
||||
line: 1,
|
||||
column: index + 5
|
||||
}
|
||||
}
|
||||
column: index + 5,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -919,14 +919,14 @@ describe('compiler: transform component slots', () => {
|
|||
start: {
|
||||
offset: index,
|
||||
line: 1,
|
||||
column: index + 1
|
||||
column: index + 1,
|
||||
},
|
||||
end: {
|
||||
offset: index + 6,
|
||||
line: 1,
|
||||
column: index + 7
|
||||
}
|
||||
}
|
||||
column: index + 7,
|
||||
},
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -940,11 +940,11 @@ describe('compiler: transform component slots', () => {
|
|||
</Comp>
|
||||
`
|
||||
const { root } = parseWithSlots(source, {
|
||||
whitespace: 'preserve'
|
||||
whitespace: 'preserve',
|
||||
})
|
||||
|
||||
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()
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -957,11 +957,11 @@ describe('compiler: transform component slots', () => {
|
|||
</Comp>
|
||||
`
|
||||
const { root } = parseWithSlots(source, {
|
||||
whitespace: 'preserve'
|
||||
whitespace: 'preserve',
|
||||
})
|
||||
|
||||
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()
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -974,7 +974,7 @@ describe('compiler: transform component slots', () => {
|
|||
</Comp>
|
||||
`
|
||||
const { root } = parseWithSlots(source, {
|
||||
whitespace: 'preserve'
|
||||
whitespace: 'preserve',
|
||||
})
|
||||
|
||||
// slots is vnodeCall's children as an ObjectExpression
|
||||
|
@ -984,7 +984,7 @@ describe('compiler: transform component slots', () => {
|
|||
// should be: header, footer, _ (no default)
|
||||
expect(slots.length).toBe(3)
|
||||
expect(
|
||||
slots.some(p => (p.key as SimpleExpressionNode).content === 'default')
|
||||
slots.some(p => (p.key as SimpleExpressionNode).content === 'default'),
|
||||
).toBe(false)
|
||||
|
||||
expect(generate(root, { prefixIdentifiers: true }).code).toMatchSnapshot()
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import { TransformContext } from '../src'
|
||||
import { Position } from '../src/ast'
|
||||
import type { TransformContext } from '../src'
|
||||
import type { Position } from '../src/ast'
|
||||
import {
|
||||
advancePositionWithClone,
|
||||
isMemberExpressionNode,
|
||||
isMemberExpressionBrowser,
|
||||
toValidAssetId
|
||||
isMemberExpressionNode,
|
||||
toValidAssetId,
|
||||
} from '../src/utils'
|
||||
|
||||
function p(line: number, column: number, offset: number): Position {
|
||||
|
@ -108,6 +108,6 @@ test('toValidAssetId', () => {
|
|||
expect(toValidAssetId('div', 'filter')).toBe('_filter_div')
|
||||
expect(toValidAssetId('foo-bar', 'component')).toBe('_component_foo_bar')
|
||||
expect(toValidAssetId('test-测试-1', 'component')).toBe(
|
||||
'_component_test_2797935797_1'
|
||||
'_component_test_2797935797_1',
|
||||
)
|
||||
})
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import { isString } from '@vue/shared'
|
||||
import {
|
||||
RENDER_SLOT,
|
||||
CREATE_SLOTS,
|
||||
RENDER_LIST,
|
||||
OPEN_BLOCK,
|
||||
FRAGMENT,
|
||||
WITH_DIRECTIVES,
|
||||
WITH_MEMO,
|
||||
CREATE_VNODE,
|
||||
CREATE_ELEMENT_VNODE,
|
||||
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'
|
||||
import { PropsExpression } from './transforms/transformElement'
|
||||
import { ImportItem, TransformContext } from './transform'
|
||||
import { Node as BabelNode } from '@babel/types'
|
||||
import type { PropsExpression } from './transforms/transformElement'
|
||||
import type { ImportItem, TransformContext } from './transform'
|
||||
import type { Node as BabelNode } from '@babel/types'
|
||||
|
||||
// Vue template is a platform-agnostic superset of HTML (syntax only).
|
||||
// More namespaces can be declared by platform specific compilers.
|
||||
|
@ -23,7 +23,7 @@ export type Namespace = number
|
|||
export enum Namespaces {
|
||||
HTML,
|
||||
SVG,
|
||||
MATH_ML
|
||||
MATH_ML,
|
||||
}
|
||||
|
||||
export enum NodeTypes {
|
||||
|
@ -57,14 +57,14 @@ export enum NodeTypes {
|
|||
JS_IF_STATEMENT,
|
||||
JS_ASSIGNMENT_EXPRESSION,
|
||||
JS_SEQUENCE_EXPRESSION,
|
||||
JS_RETURN_STATEMENT
|
||||
JS_RETURN_STATEMENT,
|
||||
}
|
||||
|
||||
export enum ElementTypes {
|
||||
ELEMENT,
|
||||
COMPONENT,
|
||||
SLOT,
|
||||
TEMPLATE
|
||||
TEMPLATE,
|
||||
}
|
||||
|
||||
export interface Node {
|
||||
|
@ -219,7 +219,7 @@ export enum ConstantTypes {
|
|||
NOT_CONSTANT = 0,
|
||||
CAN_SKIP_PATCH,
|
||||
CAN_HOIST,
|
||||
CAN_STRINGIFY
|
||||
CAN_STRINGIFY,
|
||||
}
|
||||
|
||||
export interface SimpleExpressionNode extends Node {
|
||||
|
@ -495,7 +495,7 @@ export interface RenderSlotCall extends CallExpression {
|
|||
string,
|
||||
string | ExpressionNode,
|
||||
PropsExpression | '{}',
|
||||
TemplateChildNode[]
|
||||
TemplateChildNode[],
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -582,12 +582,12 @@ export interface ForIteratorExpression extends FunctionExpression {
|
|||
export const locStub: SourceLocation = {
|
||||
start: { line: 1, column: 1, offset: 0 },
|
||||
end: { line: 1, column: 1, offset: 0 },
|
||||
source: ''
|
||||
source: '',
|
||||
}
|
||||
|
||||
export function createRoot(
|
||||
children: TemplateChildNode[],
|
||||
source = ''
|
||||
source = '',
|
||||
): RootNode {
|
||||
return {
|
||||
type: NodeTypes.ROOT,
|
||||
|
@ -601,7 +601,7 @@ export function createRoot(
|
|||
cached: 0,
|
||||
temps: 0,
|
||||
codegenNode: undefined,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -616,7 +616,7 @@ export function createVNodeCall(
|
|||
isBlock: VNodeCall['isBlock'] = false,
|
||||
disableTracking: VNodeCall['disableTracking'] = false,
|
||||
isComponent: VNodeCall['isComponent'] = false,
|
||||
loc = locStub
|
||||
loc = locStub,
|
||||
): VNodeCall {
|
||||
if (context) {
|
||||
if (isBlock) {
|
||||
|
@ -641,41 +641,41 @@ export function createVNodeCall(
|
|||
isBlock,
|
||||
disableTracking,
|
||||
isComponent,
|
||||
loc
|
||||
loc,
|
||||
}
|
||||
}
|
||||
|
||||
export function createArrayExpression(
|
||||
elements: ArrayExpression['elements'],
|
||||
loc: SourceLocation = locStub
|
||||
loc: SourceLocation = locStub,
|
||||
): ArrayExpression {
|
||||
return {
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
loc,
|
||||
elements
|
||||
elements,
|
||||
}
|
||||
}
|
||||
|
||||
export function createObjectExpression(
|
||||
properties: ObjectExpression['properties'],
|
||||
loc: SourceLocation = locStub
|
||||
loc: SourceLocation = locStub,
|
||||
): ObjectExpression {
|
||||
return {
|
||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||
loc,
|
||||
properties
|
||||
properties,
|
||||
}
|
||||
}
|
||||
|
||||
export function createObjectProperty(
|
||||
key: Property['key'] | string,
|
||||
value: Property['value']
|
||||
value: Property['value'],
|
||||
): Property {
|
||||
return {
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
loc: locStub,
|
||||
key: isString(key) ? createSimpleExpression(key, true) : key,
|
||||
value
|
||||
value,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -683,38 +683,38 @@ export function createSimpleExpression(
|
|||
content: SimpleExpressionNode['content'],
|
||||
isStatic: SimpleExpressionNode['isStatic'] = false,
|
||||
loc: SourceLocation = locStub,
|
||||
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT
|
||||
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT,
|
||||
): SimpleExpressionNode {
|
||||
return {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
loc,
|
||||
content,
|
||||
isStatic,
|
||||
constType: isStatic ? ConstantTypes.CAN_STRINGIFY : constType
|
||||
constType: isStatic ? ConstantTypes.CAN_STRINGIFY : constType,
|
||||
}
|
||||
}
|
||||
|
||||
export function createInterpolation(
|
||||
content: InterpolationNode['content'] | string,
|
||||
loc: SourceLocation
|
||||
loc: SourceLocation,
|
||||
): InterpolationNode {
|
||||
return {
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
loc,
|
||||
content: isString(content)
|
||||
? createSimpleExpression(content, false, loc)
|
||||
: content
|
||||
: content,
|
||||
}
|
||||
}
|
||||
|
||||
export function createCompoundExpression(
|
||||
children: CompoundExpressionNode['children'],
|
||||
loc: SourceLocation = locStub
|
||||
loc: SourceLocation = locStub,
|
||||
): CompoundExpressionNode {
|
||||
return {
|
||||
type: NodeTypes.COMPOUND_EXPRESSION,
|
||||
loc,
|
||||
children
|
||||
children,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -725,13 +725,13 @@ type InferCodegenNodeType<T> = T extends typeof RENDER_SLOT
|
|||
export function createCallExpression<T extends CallExpression['callee']>(
|
||||
callee: T,
|
||||
args: CallExpression['arguments'] = [],
|
||||
loc: SourceLocation = locStub
|
||||
loc: SourceLocation = locStub,
|
||||
): InferCodegenNodeType<T> {
|
||||
return {
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
loc,
|
||||
callee,
|
||||
arguments: args
|
||||
arguments: args,
|
||||
} as InferCodegenNodeType<T>
|
||||
}
|
||||
|
||||
|
@ -740,7 +740,7 @@ export function createFunctionExpression(
|
|||
returns: FunctionExpression['returns'] = undefined,
|
||||
newline: boolean = false,
|
||||
isSlot: boolean = false,
|
||||
loc: SourceLocation = locStub
|
||||
loc: SourceLocation = locStub,
|
||||
): FunctionExpression {
|
||||
return {
|
||||
type: NodeTypes.JS_FUNCTION_EXPRESSION,
|
||||
|
@ -748,7 +748,7 @@ export function createFunctionExpression(
|
|||
returns,
|
||||
newline,
|
||||
isSlot,
|
||||
loc
|
||||
loc,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -756,7 +756,7 @@ export function createConditionalExpression(
|
|||
test: ConditionalExpression['test'],
|
||||
consequent: ConditionalExpression['consequent'],
|
||||
alternate: ConditionalExpression['alternate'],
|
||||
newline = true
|
||||
newline = true,
|
||||
): ConditionalExpression {
|
||||
return {
|
||||
type: NodeTypes.JS_CONDITIONAL_EXPRESSION,
|
||||
|
@ -764,87 +764,87 @@ export function createConditionalExpression(
|
|||
consequent,
|
||||
alternate,
|
||||
newline,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
export function createCacheExpression(
|
||||
index: number,
|
||||
value: JSChildNode,
|
||||
isVNode: boolean = false
|
||||
isVNode: boolean = false,
|
||||
): CacheExpression {
|
||||
return {
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index,
|
||||
value,
|
||||
isVNode,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
export function createBlockStatement(
|
||||
body: BlockStatement['body']
|
||||
body: BlockStatement['body'],
|
||||
): BlockStatement {
|
||||
return {
|
||||
type: NodeTypes.JS_BLOCK_STATEMENT,
|
||||
body,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
export function createTemplateLiteral(
|
||||
elements: TemplateLiteral['elements']
|
||||
elements: TemplateLiteral['elements'],
|
||||
): TemplateLiteral {
|
||||
return {
|
||||
type: NodeTypes.JS_TEMPLATE_LITERAL,
|
||||
elements,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
export function createIfStatement(
|
||||
test: IfStatement['test'],
|
||||
consequent: IfStatement['consequent'],
|
||||
alternate?: IfStatement['alternate']
|
||||
alternate?: IfStatement['alternate'],
|
||||
): IfStatement {
|
||||
return {
|
||||
type: NodeTypes.JS_IF_STATEMENT,
|
||||
test,
|
||||
consequent,
|
||||
alternate,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
export function createAssignmentExpression(
|
||||
left: AssignmentExpression['left'],
|
||||
right: AssignmentExpression['right']
|
||||
right: AssignmentExpression['right'],
|
||||
): AssignmentExpression {
|
||||
return {
|
||||
type: NodeTypes.JS_ASSIGNMENT_EXPRESSION,
|
||||
left,
|
||||
right,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
export function createSequenceExpression(
|
||||
expressions: SequenceExpression['expressions']
|
||||
expressions: SequenceExpression['expressions'],
|
||||
): SequenceExpression {
|
||||
return {
|
||||
type: NodeTypes.JS_SEQUENCE_EXPRESSION,
|
||||
expressions,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
export function createReturnStatement(
|
||||
returns: ReturnStatement['returns']
|
||||
returns: ReturnStatement['returns'],
|
||||
): ReturnStatement {
|
||||
return {
|
||||
type: NodeTypes.JS_RETURN_STATEMENT,
|
||||
returns,
|
||||
loc: locStub
|
||||
loc: locStub,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -858,7 +858,7 @@ export function getVNodeBlockHelper(ssr: boolean, isComponent: boolean) {
|
|||
|
||||
export function convertToBlock(
|
||||
node: VNodeCall,
|
||||
{ helper, removeHelper, inSSR }: TransformContext
|
||||
{ helper, removeHelper, inSSR }: TransformContext,
|
||||
) {
|
||||
if (!node.isBlock) {
|
||||
node.isBlock = true
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
// should only use types from @babel/types
|
||||
// do not import runtime methods
|
||||
import type {
|
||||
BlockStatement,
|
||||
Function,
|
||||
Identifier,
|
||||
Node,
|
||||
Function,
|
||||
ObjectProperty,
|
||||
BlockStatement,
|
||||
Program
|
||||
Program,
|
||||
} from '@babel/types'
|
||||
import { walk } from 'estree-walker'
|
||||
|
||||
|
@ -17,11 +17,11 @@ export function walkIdentifiers(
|
|||
parent: Node,
|
||||
parentStack: Node[],
|
||||
isReference: boolean,
|
||||
isLocal: boolean
|
||||
isLocal: boolean,
|
||||
) => void,
|
||||
includeAll = false,
|
||||
parentStack: Node[] = [],
|
||||
knownIds: Record<string, number> = Object.create(null)
|
||||
knownIds: Record<string, number> = Object.create(null),
|
||||
) {
|
||||
if (__BROWSER__) {
|
||||
return
|
||||
|
@ -61,7 +61,7 @@ export function walkIdentifiers(
|
|||
// walk function expressions and add its arguments to known identifiers
|
||||
// so that we don't prefix them
|
||||
walkFunctionParams(node, id =>
|
||||
markScopeIdentifier(node, id, knownIds)
|
||||
markScopeIdentifier(node, id, knownIds),
|
||||
)
|
||||
}
|
||||
} else if (node.type === 'BlockStatement') {
|
||||
|
@ -70,7 +70,7 @@ export function walkIdentifiers(
|
|||
} else {
|
||||
// #3445 record block-level local variables
|
||||
walkBlockDeclarations(node, id =>
|
||||
markScopeIdentifier(node, id, knownIds)
|
||||
markScopeIdentifier(node, id, knownIds),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -85,14 +85,14 @@ export function walkIdentifiers(
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export function isReferencedIdentifier(
|
||||
id: Identifier,
|
||||
parent: Node | null,
|
||||
parentStack: Node[]
|
||||
parentStack: Node[],
|
||||
) {
|
||||
if (__BROWSER__) {
|
||||
return false
|
||||
|
@ -127,7 +127,7 @@ export function isReferencedIdentifier(
|
|||
|
||||
export function isInDestructureAssignment(
|
||||
parent: Node,
|
||||
parentStack: Node[]
|
||||
parentStack: Node[],
|
||||
): boolean {
|
||||
if (
|
||||
parent &&
|
||||
|
@ -148,7 +148,7 @@ export function isInDestructureAssignment(
|
|||
|
||||
export function walkFunctionParams(
|
||||
node: Function,
|
||||
onIdent: (id: Identifier) => void
|
||||
onIdent: (id: Identifier) => void,
|
||||
) {
|
||||
for (const p of node.params) {
|
||||
for (const id of extractIdentifiers(p)) {
|
||||
|
@ -159,7 +159,7 @@ export function walkFunctionParams(
|
|||
|
||||
export function walkBlockDeclarations(
|
||||
block: BlockStatement | Program,
|
||||
onIdent: (node: Identifier) => void
|
||||
onIdent: (node: Identifier) => void,
|
||||
) {
|
||||
for (const stmt of block.body) {
|
||||
if (stmt.type === 'VariableDeclaration') {
|
||||
|
@ -194,7 +194,7 @@ export function walkBlockDeclarations(
|
|||
|
||||
export function extractIdentifiers(
|
||||
param: Node,
|
||||
nodes: Identifier[] = []
|
||||
nodes: Identifier[] = [],
|
||||
): Identifier[] {
|
||||
switch (param.type) {
|
||||
case 'Identifier':
|
||||
|
@ -248,7 +248,7 @@ function markKnownIds(name: string, knownIds: Record<string, number>) {
|
|||
function markScopeIdentifier(
|
||||
node: Node & { scopeIds?: Set<string> },
|
||||
child: Identifier,
|
||||
knownIds: Record<string, number>
|
||||
knownIds: Record<string, number>,
|
||||
) {
|
||||
const { name } = child
|
||||
if (node.scopeIds && node.scopeIds.has(name)) {
|
||||
|
@ -453,7 +453,7 @@ export const TS_NODE_TYPES = [
|
|||
'TSTypeAssertion', // (<number>foo)
|
||||
'TSNonNullExpression', // foo!
|
||||
'TSInstantiationExpression', // foo<string>
|
||||
'TSSatisfiesExpression' // foo satisfies T
|
||||
'TSSatisfiesExpression', // foo satisfies T
|
||||
]
|
||||
|
||||
export function unwrapTSNode(node: Node): Node {
|
||||
|
|
|
@ -1,60 +1,60 @@
|
|||
import { CodegenOptions } from './options'
|
||||
import type { CodegenOptions } from './options'
|
||||
import {
|
||||
RootNode,
|
||||
TemplateChildNode,
|
||||
TextNode,
|
||||
CommentNode,
|
||||
ExpressionNode,
|
||||
type ArrayExpression,
|
||||
type AssignmentExpression,
|
||||
type CacheExpression,
|
||||
type CallExpression,
|
||||
type CommentNode,
|
||||
type CompoundExpressionNode,
|
||||
type ConditionalExpression,
|
||||
type ExpressionNode,
|
||||
type FunctionExpression,
|
||||
type IfStatement,
|
||||
type InterpolationNode,
|
||||
type JSChildNode,
|
||||
NodeTypes,
|
||||
JSChildNode,
|
||||
CallExpression,
|
||||
ArrayExpression,
|
||||
ObjectExpression,
|
||||
Position,
|
||||
InterpolationNode,
|
||||
CompoundExpressionNode,
|
||||
SimpleExpressionNode,
|
||||
FunctionExpression,
|
||||
ConditionalExpression,
|
||||
CacheExpression,
|
||||
locStub,
|
||||
SSRCodegenNode,
|
||||
TemplateLiteral,
|
||||
IfStatement,
|
||||
AssignmentExpression,
|
||||
ReturnStatement,
|
||||
VNodeCall,
|
||||
SequenceExpression,
|
||||
type ObjectExpression,
|
||||
type Position,
|
||||
type ReturnStatement,
|
||||
type RootNode,
|
||||
type SSRCodegenNode,
|
||||
type SequenceExpression,
|
||||
type SimpleExpressionNode,
|
||||
type TemplateChildNode,
|
||||
type TemplateLiteral,
|
||||
type TextNode,
|
||||
type VNodeCall,
|
||||
getVNodeBlockHelper,
|
||||
getVNodeHelper
|
||||
getVNodeHelper,
|
||||
locStub,
|
||||
} from './ast'
|
||||
import { SourceMapGenerator, RawSourceMap } from 'source-map-js'
|
||||
import { type RawSourceMap, SourceMapGenerator } from 'source-map-js'
|
||||
import {
|
||||
advancePositionWithMutation,
|
||||
assert,
|
||||
isSimpleIdentifier,
|
||||
toValidAssetId
|
||||
toValidAssetId,
|
||||
} from './utils'
|
||||
import { isString, isArray, isSymbol } from '@vue/shared'
|
||||
import { isArray, isString, isSymbol } from '@vue/shared'
|
||||
import {
|
||||
helperNameMap,
|
||||
TO_DISPLAY_STRING,
|
||||
CREATE_COMMENT,
|
||||
CREATE_ELEMENT_VNODE,
|
||||
CREATE_STATIC,
|
||||
CREATE_TEXT,
|
||||
CREATE_VNODE,
|
||||
OPEN_BLOCK,
|
||||
POP_SCOPE_ID,
|
||||
PUSH_SCOPE_ID,
|
||||
RESOLVE_COMPONENT,
|
||||
RESOLVE_DIRECTIVE,
|
||||
RESOLVE_FILTER,
|
||||
SET_BLOCK_TRACKING,
|
||||
CREATE_COMMENT,
|
||||
CREATE_TEXT,
|
||||
PUSH_SCOPE_ID,
|
||||
POP_SCOPE_ID,
|
||||
WITH_DIRECTIVES,
|
||||
CREATE_ELEMENT_VNODE,
|
||||
OPEN_BLOCK,
|
||||
CREATE_STATIC,
|
||||
TO_DISPLAY_STRING,
|
||||
WITH_CTX,
|
||||
RESOLVE_FILTER
|
||||
WITH_DIRECTIVES,
|
||||
helperNameMap,
|
||||
} from './runtimeHelpers'
|
||||
import { ImportItem } from './transform'
|
||||
import type { ImportItem } from './transform'
|
||||
|
||||
const PURE_ANNOTATION = `/*#__PURE__*/`
|
||||
|
||||
|
@ -73,7 +73,7 @@ enum NewlineType {
|
|||
Start = 0,
|
||||
End = -1,
|
||||
None = -2,
|
||||
Unknown = -3
|
||||
Unknown = -3,
|
||||
}
|
||||
|
||||
export interface CodegenContext
|
||||
|
@ -107,8 +107,8 @@ function createCodegenContext(
|
|||
ssrRuntimeModuleName = 'vue/server-renderer',
|
||||
ssr = false,
|
||||
isTS = false,
|
||||
inSSR = false
|
||||
}: CodegenOptions
|
||||
inSSR = false,
|
||||
}: CodegenOptions,
|
||||
): CodegenContext {
|
||||
const context: CodegenContext = {
|
||||
mode,
|
||||
|
@ -158,7 +158,7 @@ function createCodegenContext(
|
|||
if (__TEST__ && code.includes('\n')) {
|
||||
throw new Error(
|
||||
`CodegenContext.push() called newlineIndex: none, but contains` +
|
||||
`newlines: ${code.replace(/\n/g, '\\n')}`
|
||||
`newlines: ${code.replace(/\n/g, '\\n')}`,
|
||||
)
|
||||
}
|
||||
context.column += code.length
|
||||
|
@ -175,7 +175,7 @@ function createCodegenContext(
|
|||
) {
|
||||
throw new Error(
|
||||
`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++
|
||||
|
@ -199,7 +199,7 @@ function createCodegenContext(
|
|||
},
|
||||
newline() {
|
||||
newline(context.indentLevel)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
function newline(n: number) {
|
||||
|
@ -218,8 +218,8 @@ function createCodegenContext(
|
|||
generatedLine: context.line,
|
||||
generatedColumn: context.column - 1,
|
||||
source: filename,
|
||||
// @ts-ignore it is possible to be null
|
||||
name
|
||||
// @ts-expect-error it is possible to be null
|
||||
name,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ export function generate(
|
|||
ast: RootNode,
|
||||
options: CodegenOptions & {
|
||||
onContextCreated?: (context: CodegenContext) => void
|
||||
} = {}
|
||||
} = {},
|
||||
): CodegenResult {
|
||||
const context = createCodegenContext(ast, options)
|
||||
if (options.onContextCreated) options.onContextCreated(context)
|
||||
|
@ -249,7 +249,7 @@ export function generate(
|
|||
deindent,
|
||||
newline,
|
||||
scopeId,
|
||||
ssr
|
||||
ssr,
|
||||
} = context
|
||||
|
||||
const helpers = Array.from(ast.helpers)
|
||||
|
@ -296,7 +296,7 @@ export function generate(
|
|||
if (hasHelpers) {
|
||||
push(
|
||||
`const { ${helpers.map(aliasHelper).join(', ')} } = _Vue\n`,
|
||||
NewlineType.End
|
||||
NewlineType.End,
|
||||
)
|
||||
newline()
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ export function generate(
|
|||
ast,
|
||||
code: context.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,
|
||||
runtimeModuleName,
|
||||
runtimeGlobalName,
|
||||
ssrRuntimeModuleName
|
||||
ssrRuntimeModuleName,
|
||||
} = context
|
||||
const VueBinding =
|
||||
!__BROWSER__ && ssr
|
||||
|
@ -381,7 +381,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
|
|||
if (!__BROWSER__ && prefixIdentifiers) {
|
||||
push(
|
||||
`const { ${helpers.map(aliasHelper).join(', ')} } = ${VueBinding}\n`,
|
||||
NewlineType.End
|
||||
NewlineType.End,
|
||||
)
|
||||
} else {
|
||||
// "with" mode.
|
||||
|
@ -396,7 +396,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
|
|||
CREATE_ELEMENT_VNODE,
|
||||
CREATE_COMMENT,
|
||||
CREATE_TEXT,
|
||||
CREATE_STATIC
|
||||
CREATE_STATIC,
|
||||
]
|
||||
.filter(helper => helpers.includes(helper))
|
||||
.map(aliasHelper)
|
||||
|
@ -412,7 +412,7 @@ function genFunctionPreamble(ast: RootNode, context: CodegenContext) {
|
|||
`const { ${ast.ssrHelpers
|
||||
.map(aliasHelper)
|
||||
.join(', ')} } = require("${ssrRuntimeModuleName}")\n`,
|
||||
NewlineType.End
|
||||
NewlineType.End,
|
||||
)
|
||||
}
|
||||
genHoists(ast.hoists, context)
|
||||
|
@ -424,14 +424,14 @@ function genModulePreamble(
|
|||
ast: RootNode,
|
||||
context: CodegenContext,
|
||||
genScopeId: boolean,
|
||||
inline?: boolean
|
||||
inline?: boolean,
|
||||
) {
|
||||
const {
|
||||
push,
|
||||
newline,
|
||||
optimizeImports,
|
||||
runtimeModuleName,
|
||||
ssrRuntimeModuleName
|
||||
ssrRuntimeModuleName,
|
||||
} = context
|
||||
|
||||
if (genScopeId && ast.hoists.length) {
|
||||
|
@ -452,20 +452,20 @@ function genModulePreamble(
|
|||
`import { ${helpers
|
||||
.map(s => helperNameMap[s])
|
||||
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`,
|
||||
NewlineType.End
|
||||
NewlineType.End,
|
||||
)
|
||||
push(
|
||||
`\n// Binding optimization for webpack code-split\nconst ${helpers
|
||||
.map(s => `_${helperNameMap[s]} = ${helperNameMap[s]}`)
|
||||
.join(', ')}\n`,
|
||||
NewlineType.End
|
||||
NewlineType.End,
|
||||
)
|
||||
} else {
|
||||
push(
|
||||
`import { ${helpers
|
||||
.map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
|
||||
.join(', ')} } from ${JSON.stringify(runtimeModuleName)}\n`,
|
||||
NewlineType.End
|
||||
NewlineType.End,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -475,7 +475,7 @@ function genModulePreamble(
|
|||
`import { ${ast.ssrHelpers
|
||||
.map(s => `${helperNameMap[s]} as _${helperNameMap[s]}`)
|
||||
.join(', ')} } from "${ssrRuntimeModuleName}"\n`,
|
||||
NewlineType.End
|
||||
NewlineType.End,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -495,14 +495,14 @@ function genModulePreamble(
|
|||
function genAssets(
|
||||
assets: string[],
|
||||
type: 'component' | 'directive' | 'filter',
|
||||
{ helper, push, newline, isTS }: CodegenContext
|
||||
{ helper, push, newline, isTS }: CodegenContext,
|
||||
) {
|
||||
const resolver = helper(
|
||||
__COMPAT__ && type === 'filter'
|
||||
? RESOLVE_FILTER
|
||||
: type === 'component'
|
||||
? RESOLVE_COMPONENT
|
||||
: RESOLVE_DIRECTIVE
|
||||
: RESOLVE_DIRECTIVE,
|
||||
)
|
||||
for (let i = 0; i < assets.length; i++) {
|
||||
let id = assets[i]
|
||||
|
@ -514,7 +514,7 @@ function genAssets(
|
|||
push(
|
||||
`const ${toValidAssetId(id, type)} = ${resolver}(${JSON.stringify(id)}${
|
||||
maybeSelfReference ? `, true` : ``
|
||||
})${isTS ? `!` : ``}`
|
||||
})${isTS ? `!` : ``}`,
|
||||
)
|
||||
if (i < assets.length - 1) {
|
||||
newline()
|
||||
|
@ -535,8 +535,8 @@ function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) {
|
|||
if (genScopeId) {
|
||||
push(
|
||||
`const _withScopeId = n => (${helper(
|
||||
PUSH_SCOPE_ID
|
||||
)}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)`
|
||||
PUSH_SCOPE_ID,
|
||||
)}("${scopeId}"),n=n(),${helper(POP_SCOPE_ID)}(),n)`,
|
||||
)
|
||||
newline()
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ function genHoists(hoists: (JSChildNode | null)[], context: CodegenContext) {
|
|||
push(
|
||||
`const _hoisted_${i + 1} = ${
|
||||
needScopeIdWrapper ? `${PURE_ANNOTATION} _withScopeId(() => ` : ``
|
||||
}`
|
||||
}`,
|
||||
)
|
||||
genNode(exp, context)
|
||||
if (needScopeIdWrapper) {
|
||||
|
@ -585,7 +585,7 @@ function isText(n: string | CodegenNode) {
|
|||
|
||||
function genNodeListAsArray(
|
||||
nodes: (string | CodegenNode | TemplateChildNode[])[],
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
const multilines =
|
||||
nodes.length > 3 ||
|
||||
|
@ -601,7 +601,7 @@ function genNodeList(
|
|||
nodes: (string | symbol | CodegenNode | TemplateChildNode[])[],
|
||||
context: CodegenContext,
|
||||
multilines: boolean = false,
|
||||
comma: boolean = true
|
||||
comma: boolean = true,
|
||||
) {
|
||||
const { push, newline } = context
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
|
@ -641,7 +641,7 @@ function genNode(node: CodegenNode | symbol | string, context: CodegenContext) {
|
|||
assert(
|
||||
node.codegenNode != null,
|
||||
`Codegen node is missing for element/if/for node. ` +
|
||||
`Apply appropriate transforms first.`
|
||||
`Apply appropriate transforms first.`,
|
||||
)
|
||||
genNode(node.codegenNode!, context)
|
||||
break
|
||||
|
@ -722,7 +722,7 @@ function genNode(node: CodegenNode | symbol | string, context: CodegenContext) {
|
|||
|
||||
function genText(
|
||||
node: TextNode | SimpleExpressionNode,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
context.push(JSON.stringify(node.content), NewlineType.Unknown, node)
|
||||
}
|
||||
|
@ -732,7 +732,7 @@ function genExpression(node: SimpleExpressionNode, context: CodegenContext) {
|
|||
context.push(
|
||||
isStatic ? JSON.stringify(content) : content,
|
||||
NewlineType.Unknown,
|
||||
node
|
||||
node,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -746,7 +746,7 @@ function genInterpolation(node: InterpolationNode, context: CodegenContext) {
|
|||
|
||||
function genCompoundExpression(
|
||||
node: CompoundExpressionNode,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
for (let i = 0; i < node.children!.length; i++) {
|
||||
const child = node.children![i]
|
||||
|
@ -760,7 +760,7 @@ function genCompoundExpression(
|
|||
|
||||
function genExpressionAsPropertyKey(
|
||||
node: ExpressionNode,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
const { push } = context
|
||||
if (node.type === NodeTypes.COMPOUND_EXPRESSION) {
|
||||
|
@ -786,7 +786,7 @@ function genComment(node: CommentNode, context: CodegenContext) {
|
|||
push(
|
||||
`${helper(CREATE_COMMENT)}(${JSON.stringify(node.content)})`,
|
||||
NewlineType.Unknown,
|
||||
node
|
||||
node,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -801,7 +801,7 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
|
|||
directives,
|
||||
isBlock,
|
||||
disableTracking,
|
||||
isComponent
|
||||
isComponent,
|
||||
} = node
|
||||
if (directives) {
|
||||
push(helper(WITH_DIRECTIVES) + `(`)
|
||||
|
@ -818,7 +818,7 @@ function genVNodeCall(node: VNodeCall, context: CodegenContext) {
|
|||
push(helper(callHelper) + `(`, NewlineType.None, node)
|
||||
genNodeList(
|
||||
genNullableArgs([tag, props, children, patchFlag, dynamicProps]),
|
||||
context
|
||||
context,
|
||||
)
|
||||
push(`)`)
|
||||
if (isBlock) {
|
||||
|
@ -887,7 +887,7 @@ function genArrayExpression(node: ArrayExpression, context: CodegenContext) {
|
|||
|
||||
function genFunctionExpression(
|
||||
node: FunctionExpression,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
const { push, indent, deindent } = context
|
||||
const { params, returns, body, newline, isSlot } = node
|
||||
|
@ -932,7 +932,7 @@ function genFunctionExpression(
|
|||
|
||||
function genConditionalExpression(
|
||||
node: ConditionalExpression,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
const { test, consequent, alternate, newline: needNewline } = node
|
||||
const { push, indent, deindent, newline } = context
|
||||
|
@ -1033,7 +1033,7 @@ function genIfStatement(node: IfStatement, context: CodegenContext) {
|
|||
|
||||
function genAssignmentExpression(
|
||||
node: AssignmentExpression,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
genNode(node.left, context)
|
||||
context.push(` = `)
|
||||
|
@ -1042,7 +1042,7 @@ function genAssignmentExpression(
|
|||
|
||||
function genSequenceExpression(
|
||||
node: SequenceExpression,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
context.push(`(`)
|
||||
genNodeList(node.expressions, context)
|
||||
|
@ -1051,7 +1051,7 @@ function genSequenceExpression(
|
|||
|
||||
function genReturnStatement(
|
||||
{ returns }: ReturnStatement,
|
||||
context: CodegenContext
|
||||
context: CodegenContext,
|
||||
) {
|
||||
context.push(`return `)
|
||||
if (isArray(returns)) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { SourceLocation } from '../ast'
|
||||
import { CompilerError } from '../errors'
|
||||
import { MergedParserOptions } from '../parser'
|
||||
import { TransformContext } from '../transform'
|
||||
import type { SourceLocation } from '../ast'
|
||||
import type { CompilerError } from '../errors'
|
||||
import type { MergedParserOptions } from '../parser'
|
||||
import type { TransformContext } from '../transform'
|
||||
|
||||
export type CompilerCompatConfig = Partial<
|
||||
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_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',
|
||||
COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',
|
||||
COMPILER_FILTERS = 'COMPILER_FILTER'
|
||||
COMPILER_FILTERS = 'COMPILER_FILTER',
|
||||
}
|
||||
|
||||
type DeprecationData = {
|
||||
|
@ -35,7 +35,7 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
|||
`Platform-native elements with "is" prop will no longer be ` +
|
||||
`treated as components in Vue 3 unless the "is" value is explicitly ` +
|
||||
`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]: {
|
||||
|
@ -43,7 +43,7 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
|||
`.sync modifier for v-bind has been removed. Use v-model with ` +
|
||||
`argument instead. \`v-bind:${key}.sync\` should be changed to ` +
|
||||
`\`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]: {
|
||||
|
@ -53,12 +53,12 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
|||
`that appears before v-bind in the case of conflict. ` +
|
||||
`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.`,
|
||||
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]: {
|
||||
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]: {
|
||||
|
@ -68,18 +68,18 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
|||
`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 ` +
|
||||
`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]: {
|
||||
message:
|
||||
`<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]: {
|
||||
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]: {
|
||||
|
@ -87,13 +87,13 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
|||
`filters have been removed in Vue 3. ` +
|
||||
`The "|" symbol will be treated as native JavaScript bitwise OR operator. ` +
|
||||
`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(
|
||||
key: CompilerDeprecationTypes | 'MODE',
|
||||
{ compatConfig }: MergedParserOptions | TransformContext
|
||||
{ compatConfig }: MergedParserOptions | TransformContext,
|
||||
) {
|
||||
const value = compatConfig && compatConfig[key]
|
||||
if (key === 'MODE') {
|
||||
|
@ -105,7 +105,7 @@ function getCompatValue(
|
|||
|
||||
export function isCompatEnabled(
|
||||
key: CompilerDeprecationTypes,
|
||||
context: MergedParserOptions | TransformContext
|
||||
context: MergedParserOptions | TransformContext,
|
||||
) {
|
||||
const mode = getCompatValue('MODE', context)
|
||||
const value = getCompatValue(key, context)
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { RESOLVE_FILTER } from '../runtimeHelpers'
|
||||
import {
|
||||
ExpressionNode,
|
||||
AttributeNode,
|
||||
DirectiveNode,
|
||||
type AttributeNode,
|
||||
type DirectiveNode,
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
SimpleExpressionNode
|
||||
type SimpleExpressionNode,
|
||||
} from '../ast'
|
||||
import {
|
||||
CompilerDeprecationTypes,
|
||||
isCompatEnabled,
|
||||
warnDeprecation
|
||||
warnDeprecation,
|
||||
} from './compatConfig'
|
||||
import { NodeTransform, TransformContext } from '../transform'
|
||||
import type { NodeTransform, TransformContext } from '../transform'
|
||||
import { toValidAssetId } from '../utils'
|
||||
|
||||
const validDivisionCharRE = /[\w).+\-_$\]]/
|
||||
|
@ -162,7 +162,7 @@ function parseFilter(node: SimpleExpressionNode, context: TransformContext) {
|
|||
warnDeprecation(
|
||||
CompilerDeprecationTypes.COMPILER_FILTERS,
|
||||
context,
|
||||
node.loc
|
||||
node.loc,
|
||||
)
|
||||
for (i = 0; i < filters.length; i++) {
|
||||
expression = wrapFilter(expression, filters[i], context)
|
||||
|
@ -174,7 +174,7 @@ function parseFilter(node: SimpleExpressionNode, context: TransformContext) {
|
|||
function wrapFilter(
|
||||
exp: string,
|
||||
filter: string,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): string {
|
||||
context.helper(RESOLVE_FILTER)
|
||||
const i = filter.indexOf('(')
|
||||
|
|
|
@ -1,9 +1,13 @@
|
|||
import { CompilerOptions } from './options'
|
||||
import type { CompilerOptions } from './options'
|
||||
import { baseParse } from './parser'
|
||||
import { transform, NodeTransform, DirectiveTransform } from './transform'
|
||||
import { generate, CodegenResult } from './codegen'
|
||||
import { RootNode } from './ast'
|
||||
import { isString, extend } from '@vue/shared'
|
||||
import {
|
||||
type DirectiveTransform,
|
||||
type NodeTransform,
|
||||
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 { transformFor } from './transforms/vFor'
|
||||
import { transformExpression } from './transforms/transformExpression'
|
||||
|
@ -16,16 +20,16 @@ import { transformText } from './transforms/transformText'
|
|||
import { transformOnce } from './transforms/vOnce'
|
||||
import { transformModel } from './transforms/vModel'
|
||||
import { transformFilter } from './compat/transformFilter'
|
||||
import { defaultOnError, createCompilerError, ErrorCodes } from './errors'
|
||||
import { ErrorCodes, createCompilerError, defaultOnError } from './errors'
|
||||
import { transformMemo } from './transforms/vMemo'
|
||||
|
||||
export type TransformPreset = [
|
||||
NodeTransform[],
|
||||
Record<string, DirectiveTransform>
|
||||
Record<string, DirectiveTransform>,
|
||||
]
|
||||
|
||||
export function getBaseTransformPreset(
|
||||
prefixIdentifiers?: boolean
|
||||
prefixIdentifiers?: boolean,
|
||||
): TransformPreset {
|
||||
return [
|
||||
[
|
||||
|
@ -38,7 +42,7 @@ export function getBaseTransformPreset(
|
|||
? [
|
||||
// order is important
|
||||
trackVForSlotScopes,
|
||||
transformExpression
|
||||
transformExpression,
|
||||
]
|
||||
: __BROWSER__ && __DEV__
|
||||
? [transformExpression]
|
||||
|
@ -46,13 +50,13 @@ export function getBaseTransformPreset(
|
|||
transformSlotOutlet,
|
||||
transformElement,
|
||||
trackSlotScopes,
|
||||
transformText
|
||||
transformText,
|
||||
],
|
||||
{
|
||||
on: transformOn,
|
||||
bind: transformBind,
|
||||
model: transformModel
|
||||
}
|
||||
model: transformModel,
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
|
@ -60,7 +64,7 @@ export function getBaseTransformPreset(
|
|||
// @vue/compiler-dom can export `compile` while re-exporting everything else.
|
||||
export function baseCompile(
|
||||
source: string | RootNode,
|
||||
options: CompilerOptions = {}
|
||||
options: CompilerOptions = {},
|
||||
): CodegenResult {
|
||||
const onError = options.onError || defaultOnError
|
||||
const isModuleMode = options.mode === 'module'
|
||||
|
@ -83,7 +87,7 @@ export function baseCompile(
|
|||
}
|
||||
|
||||
const resolvedOptions = extend({}, options, {
|
||||
prefixIdentifiers
|
||||
prefixIdentifiers,
|
||||
})
|
||||
const ast = isString(source) ? baseParse(source, resolvedOptions) : source
|
||||
const [nodeTransforms, directiveTransforms] =
|
||||
|
@ -101,14 +105,14 @@ export function baseCompile(
|
|||
extend({}, resolvedOptions, {
|
||||
nodeTransforms: [
|
||||
...nodeTransforms,
|
||||
...(options.nodeTransforms || []) // user transforms
|
||||
...(options.nodeTransforms || []), // user transforms
|
||||
],
|
||||
directiveTransforms: extend(
|
||||
{},
|
||||
directiveTransforms,
|
||||
options.directiveTransforms || {} // user transforms
|
||||
)
|
||||
})
|
||||
options.directiveTransforms || {}, // user transforms
|
||||
),
|
||||
}),
|
||||
)
|
||||
|
||||
return generate(ast, resolvedOptions)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { SourceLocation } from './ast'
|
||||
import type { SourceLocation } from './ast'
|
||||
|
||||
export interface CompilerError extends SyntaxError {
|
||||
code: number | string
|
||||
|
@ -25,7 +25,7 @@ export function createCompilerError<T extends number>(
|
|||
code: T,
|
||||
loc?: SourceLocation,
|
||||
messages?: { [code: number]: string },
|
||||
additionalMessage?: string
|
||||
additionalMessage?: string,
|
||||
): InferCompilerError<T> {
|
||||
const msg =
|
||||
__DEV__ || !__BROWSER__
|
||||
|
@ -101,7 +101,7 @@ export enum ErrorCodes {
|
|||
// 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
|
||||
// item.
|
||||
__EXTEND_POINT__
|
||||
__EXTEND_POINT__,
|
||||
}
|
||||
|
||||
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.`,
|
||||
|
||||
// just to fulfill types
|
||||
[ErrorCodes.__EXTEND_POINT__]: ``
|
||||
[ErrorCodes.__EXTEND_POINT__]: ``,
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ export {
|
|||
type CodegenOptions,
|
||||
type HoistTransform,
|
||||
type BindingMetadata,
|
||||
BindingTypes
|
||||
BindingTypes,
|
||||
} from './options'
|
||||
export { baseParse } from './parser'
|
||||
export {
|
||||
|
@ -19,7 +19,7 @@ export {
|
|||
createStructuralDirectiveTransform,
|
||||
type NodeTransform,
|
||||
type StructuralDirectiveTransform,
|
||||
type DirectiveTransform
|
||||
type DirectiveTransform,
|
||||
} from './transform'
|
||||
export { generate, type CodegenContext, type CodegenResult } from './codegen'
|
||||
export {
|
||||
|
@ -27,7 +27,7 @@ export {
|
|||
errorMessages,
|
||||
createCompilerError,
|
||||
type CoreCompilerError,
|
||||
type CompilerError
|
||||
type CompilerError,
|
||||
} from './errors'
|
||||
|
||||
export * from './ast'
|
||||
|
@ -45,20 +45,20 @@ export { processFor, createForLoopParams } from './transforms/vFor'
|
|||
export {
|
||||
transformExpression,
|
||||
processExpression,
|
||||
stringifyExpression
|
||||
stringifyExpression,
|
||||
} from './transforms/transformExpression'
|
||||
export {
|
||||
buildSlots,
|
||||
type SlotFnBuilder,
|
||||
trackVForSlotScopes,
|
||||
trackSlotScopes
|
||||
trackSlotScopes,
|
||||
} from './transforms/vSlot'
|
||||
export {
|
||||
transformElement,
|
||||
resolveComponentType,
|
||||
buildProps,
|
||||
buildDirectiveArgs,
|
||||
type PropsExpression
|
||||
type PropsExpression,
|
||||
} from './transforms/transformElement'
|
||||
export { processSlotOutlet } from './transforms/transformSlotOutlet'
|
||||
export { getConstantType } from './transforms/hoistStatic'
|
||||
|
@ -68,5 +68,5 @@ export { generateCodeFrame } from '@vue/shared'
|
|||
export {
|
||||
checkCompatEnabled,
|
||||
warnDeprecation,
|
||||
CompilerDeprecationTypes
|
||||
CompilerDeprecationTypes,
|
||||
} from './compat/compatConfig'
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
import {
|
||||
import type {
|
||||
ElementNode,
|
||||
Namespace,
|
||||
TemplateChildNode,
|
||||
Namespaces,
|
||||
ParentNode,
|
||||
Namespaces
|
||||
TemplateChildNode,
|
||||
} from './ast'
|
||||
import { CompilerError } from './errors'
|
||||
import {
|
||||
NodeTransform,
|
||||
import type { CompilerError } from './errors'
|
||||
import type {
|
||||
DirectiveTransform,
|
||||
TransformContext
|
||||
NodeTransform,
|
||||
TransformContext,
|
||||
} from './transform'
|
||||
import { CompilerCompatOptions } from './compat/compatConfig'
|
||||
import { ParserPlugin } from '@babel/parser'
|
||||
import type { CompilerCompatOptions } from './compat/compatConfig'
|
||||
import type { ParserPlugin } from '@babel/parser'
|
||||
|
||||
export interface ErrorHandlingOptions {
|
||||
onWarn?: (warning: CompilerError) => void
|
||||
|
@ -66,7 +66,7 @@ export interface ParserOptions
|
|||
getNamespace?: (
|
||||
tag: string,
|
||||
parent: ElementNode | undefined,
|
||||
rootNamespace: Namespace
|
||||
rootNamespace: Namespace,
|
||||
) => Namespace
|
||||
/**
|
||||
* @default ['{{', '}}']
|
||||
|
@ -102,7 +102,7 @@ export interface ParserOptions
|
|||
export type HoistTransform = (
|
||||
children: TemplateChildNode[],
|
||||
context: TransformContext,
|
||||
parent: ParentNode
|
||||
parent: ParentNode,
|
||||
) => void
|
||||
|
||||
export enum BindingTypes {
|
||||
|
@ -148,7 +148,7 @@ export enum BindingTypes {
|
|||
/**
|
||||
* a literal constant, e.g. 'foo', 1, true
|
||||
*/
|
||||
LITERAL_CONST = 'literal-const'
|
||||
LITERAL_CONST = 'literal-const',
|
||||
}
|
||||
|
||||
export type BindingMetadata = {
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import {
|
||||
AttributeNode,
|
||||
type AttributeNode,
|
||||
ConstantTypes,
|
||||
DirectiveNode,
|
||||
ElementNode,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
ForParseResult,
|
||||
type ForParseResult,
|
||||
Namespaces,
|
||||
NodeTypes,
|
||||
RootNode,
|
||||
SimpleExpressionNode,
|
||||
SourceLocation,
|
||||
TemplateChildNode,
|
||||
type RootNode,
|
||||
type SimpleExpressionNode,
|
||||
type SourceLocation,
|
||||
type TemplateChildNode,
|
||||
createRoot,
|
||||
createSimpleExpression
|
||||
createSimpleExpression,
|
||||
} from './ast'
|
||||
import { ParserOptions } from './options'
|
||||
import type { ParserOptions } from './options'
|
||||
import Tokenizer, {
|
||||
CharCodes,
|
||||
ParseMode,
|
||||
|
@ -22,33 +22,33 @@ import Tokenizer, {
|
|||
Sequences,
|
||||
State,
|
||||
isWhitespace,
|
||||
toCharCodes
|
||||
toCharCodes,
|
||||
} from './tokenizer'
|
||||
import {
|
||||
CompilerCompatOptions,
|
||||
type CompilerCompatOptions,
|
||||
CompilerDeprecationTypes,
|
||||
checkCompatEnabled,
|
||||
isCompatEnabled,
|
||||
warnDeprecation
|
||||
warnDeprecation,
|
||||
} from './compat/compatConfig'
|
||||
import { NO, extend } from '@vue/shared'
|
||||
import {
|
||||
ErrorCodes,
|
||||
createCompilerError,
|
||||
defaultOnError,
|
||||
defaultOnWarn
|
||||
defaultOnWarn,
|
||||
} from './errors'
|
||||
import {
|
||||
forAliasRE,
|
||||
isCoreComponent,
|
||||
isSimpleIdentifier,
|
||||
isStaticArgOf
|
||||
isStaticArgOf,
|
||||
} from './utils'
|
||||
import { decodeHTML } from 'entities/lib/decode.js'
|
||||
import {
|
||||
type ParserOptions as BabelOptions,
|
||||
parse,
|
||||
parseExpression,
|
||||
type ParserOptions as BabelOptions
|
||||
} from '@babel/parser'
|
||||
|
||||
type OptionalOptions =
|
||||
|
@ -76,7 +76,7 @@ export const defaultParserOptions: MergedParserOptions = {
|
|||
onError: defaultOnError,
|
||||
onWarn: defaultOnWarn,
|
||||
comments: __DEV__,
|
||||
prefixIdentifiers: false
|
||||
prefixIdentifiers: false,
|
||||
}
|
||||
|
||||
let currentOptions: MergedParserOptions = defaultParserOptions
|
||||
|
@ -129,7 +129,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
addNode({
|
||||
type: NodeTypes.INTERPOLATION,
|
||||
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: [],
|
||||
children: [],
|
||||
loc: getLoc(start - 1, end),
|
||||
codegenNode: undefined
|
||||
codegenNode: undefined,
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -191,7 +191,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
name: getSlice(start, end),
|
||||
nameLoc: getLoc(start, end),
|
||||
value: undefined,
|
||||
loc: getLoc(start)
|
||||
loc: getLoc(start),
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -216,7 +216,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
name: raw,
|
||||
nameLoc: getLoc(start, end),
|
||||
value: undefined,
|
||||
loc: getLoc(start)
|
||||
loc: getLoc(start),
|
||||
}
|
||||
} else {
|
||||
currentProp = {
|
||||
|
@ -226,7 +226,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
exp: undefined,
|
||||
arg: undefined,
|
||||
modifiers: raw === '.' ? ['prop'] : [],
|
||||
loc: getLoc(start)
|
||||
loc: getLoc(start),
|
||||
}
|
||||
if (name === 'pre') {
|
||||
inVPre = tokenizer.inVPre = true
|
||||
|
@ -254,7 +254,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
isStatic ? arg : arg.slice(1, -1),
|
||||
isStatic,
|
||||
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
|
||||
if (
|
||||
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)
|
||||
|
@ -314,7 +314,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
if (__BROWSER__ && currentAttrValue.includes('&')) {
|
||||
currentAttrValue = currentOptions.decodeEntities!(
|
||||
currentAttrValue,
|
||||
true
|
||||
true,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -336,7 +336,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
loc:
|
||||
quote === QuoteType.Unquoted
|
||||
? getLoc(currentAttrStartIndex, currentAttrEndIndex)
|
||||
: getLoc(currentAttrStartIndex - 1, currentAttrEndIndex + 1)
|
||||
: getLoc(currentAttrStartIndex - 1, currentAttrEndIndex + 1),
|
||||
}
|
||||
if (
|
||||
tokenizer.inSFCRoot &&
|
||||
|
@ -369,7 +369,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
false,
|
||||
getLoc(currentAttrStartIndex, currentAttrEndIndex),
|
||||
ConstantTypes.NOT_CONSTANT,
|
||||
expParseMode
|
||||
expParseMode,
|
||||
)
|
||||
if (currentProp.name === 'for') {
|
||||
currentProp.forParseResult = parseForExpression(currentProp.exp)
|
||||
|
@ -384,7 +384,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
CompilerDeprecationTypes.COMPILER_V_BIND_SYNC,
|
||||
currentOptions,
|
||||
currentProp.loc,
|
||||
currentProp.rawName
|
||||
currentProp.rawName,
|
||||
)
|
||||
) {
|
||||
currentProp.name = 'model'
|
||||
|
@ -408,7 +408,7 @@ const tokenizer = new Tokenizer(stack, {
|
|||
addNode({
|
||||
type: NodeTypes.COMMENT,
|
||||
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:
|
||||
emitError(
|
||||
ErrorCodes.X_MISSING_INTERPOLATION_END,
|
||||
tokenizer.sectionStart
|
||||
tokenizer.sectionStart,
|
||||
)
|
||||
break
|
||||
case State.InCommentLike:
|
||||
|
@ -476,10 +476,10 @@ const tokenizer = new Tokenizer(stack, {
|
|||
if ((stack[0] ? stack[0].ns : currentOptions.ns) === Namespaces.HTML) {
|
||||
emitError(
|
||||
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,
|
||||
|
@ -488,7 +488,7 @@ const forIteratorRE = /,([^,\}\]]*)(?:,([^,\}\]]*))?$/
|
|||
const stripParensRE = /^\(|\)$/g
|
||||
|
||||
function parseForExpression(
|
||||
input: SimpleExpressionNode
|
||||
input: SimpleExpressionNode,
|
||||
): ForParseResult | undefined {
|
||||
const loc = input.loc
|
||||
const exp = input.content
|
||||
|
@ -500,7 +500,7 @@ function parseForExpression(
|
|||
const createAliasExpression = (
|
||||
content: string,
|
||||
offset: number,
|
||||
asParam = false
|
||||
asParam = false,
|
||||
) => {
|
||||
const start = loc.start.offset + offset
|
||||
const end = start + content.length
|
||||
|
@ -509,7 +509,7 @@ function parseForExpression(
|
|||
false,
|
||||
getLoc(start, end),
|
||||
ConstantTypes.NOT_CONSTANT,
|
||||
asParam ? ExpParseMode.Params : ExpParseMode.Normal
|
||||
asParam ? ExpParseMode.Params : ExpParseMode.Normal,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -518,7 +518,7 @@ function parseForExpression(
|
|||
value: undefined,
|
||||
key: undefined,
|
||||
index: undefined,
|
||||
finalized: false
|
||||
finalized: false,
|
||||
}
|
||||
|
||||
let valueContent = LHS.trim().replace(stripParensRE, '').trim()
|
||||
|
@ -545,9 +545,9 @@ function parseForExpression(
|
|||
indexContent,
|
||||
result.key
|
||||
? 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({
|
||||
type: NodeTypes.TEXT,
|
||||
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!.start.offset,
|
||||
el.innerLoc!.end.offset
|
||||
el.innerLoc!.end.offset,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -666,7 +666,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
|||
__DEV__ &&
|
||||
isCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,
|
||||
currentOptions
|
||||
currentOptions,
|
||||
)
|
||||
) {
|
||||
let hasIf = false
|
||||
|
@ -684,7 +684,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
|||
warnDeprecation(
|
||||
CompilerDeprecationTypes.COMPILER_V_IF_V_FOR_PRECEDENCE,
|
||||
currentOptions,
|
||||
el.loc
|
||||
el.loc,
|
||||
)
|
||||
break
|
||||
}
|
||||
|
@ -694,7 +694,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
|||
if (
|
||||
isCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,
|
||||
currentOptions
|
||||
currentOptions,
|
||||
) &&
|
||||
el.tag === 'template' &&
|
||||
!isFragmentTemplate(el)
|
||||
|
@ -703,7 +703,7 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
|||
warnDeprecation(
|
||||
CompilerDeprecationTypes.COMPILER_NATIVE_TEMPLATE,
|
||||
currentOptions,
|
||||
el.loc
|
||||
el.loc,
|
||||
)
|
||||
// unwrap
|
||||
const parent = stack[0] || currentRoot
|
||||
|
@ -712,14 +712,14 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
|||
}
|
||||
|
||||
const inlineTemplateProp = props.find(
|
||||
p => p.type === NodeTypes.ATTRIBUTE && p.name === 'inline-template'
|
||||
p => p.type === NodeTypes.ATTRIBUTE && p.name === 'inline-template',
|
||||
) as AttributeNode
|
||||
if (
|
||||
inlineTemplateProp &&
|
||||
checkCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_INLINE_TEMPLATE,
|
||||
currentOptions,
|
||||
inlineTemplateProp.loc
|
||||
inlineTemplateProp.loc,
|
||||
) &&
|
||||
el.children.length
|
||||
) {
|
||||
|
@ -727,9 +727,9 @@ function onCloseTag(el: ElementNode, end: number, isImplied = false) {
|
|||
type: NodeTypes.TEXT,
|
||||
content: getSlice(
|
||||
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(
|
||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||
currentOptions,
|
||||
p.loc
|
||||
p.loc,
|
||||
)
|
||||
) {
|
||||
return true
|
||||
|
@ -796,7 +796,7 @@ function isComponent({ tag, props }: ElementNode): boolean {
|
|||
checkCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||
currentOptions,
|
||||
p.loc
|
||||
p.loc,
|
||||
)
|
||||
) {
|
||||
return true
|
||||
|
@ -812,7 +812,7 @@ function isUpperCase(c: number) {
|
|||
const windowsNewlineRE = /\r\n/g
|
||||
function condenseWhitespace(
|
||||
nodes: TemplateChildNode[],
|
||||
tag?: string
|
||||
tag?: string,
|
||||
): TemplateChildNode[] {
|
||||
const shouldCondense = currentOptions.whitespace !== 'preserve'
|
||||
let removedWhitespace = false
|
||||
|
@ -915,7 +915,7 @@ function getLoc(start: number, end?: number): SourceLocation {
|
|||
// @ts-expect-error allow late attachment
|
||||
end: end == null ? end : tokenizer.getPos(end),
|
||||
// @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!,
|
||||
nameLoc: getLoc(
|
||||
dir.loc.start.offset,
|
||||
dir.loc.start.offset + dir.rawName!.length
|
||||
dir.loc.start.offset + dir.rawName!.length,
|
||||
),
|
||||
value: undefined,
|
||||
loc: dir.loc
|
||||
loc: dir.loc,
|
||||
}
|
||||
if (dir.exp) {
|
||||
// account for quotes
|
||||
|
@ -947,7 +947,7 @@ function dirToAttr(dir: DirectiveNode): AttributeNode {
|
|||
attr.value = {
|
||||
type: NodeTypes.TEXT,
|
||||
content: (dir.exp as SimpleExpressionNode).content,
|
||||
loc
|
||||
loc,
|
||||
}
|
||||
}
|
||||
return attr
|
||||
|
@ -957,7 +957,7 @@ enum ExpParseMode {
|
|||
Normal,
|
||||
Params,
|
||||
Statements,
|
||||
Skip
|
||||
Skip,
|
||||
}
|
||||
|
||||
function createExp(
|
||||
|
@ -965,7 +965,7 @@ function createExp(
|
|||
isStatic: SimpleExpressionNode['isStatic'] = false,
|
||||
loc: SourceLocation,
|
||||
constType: ConstantTypes = ConstantTypes.NOT_CONSTANT,
|
||||
parseMode = ExpParseMode.Normal
|
||||
parseMode = ExpParseMode.Normal,
|
||||
) {
|
||||
const exp = createSimpleExpression(content, isStatic, loc, constType)
|
||||
if (
|
||||
|
@ -982,7 +982,7 @@ function createExp(
|
|||
try {
|
||||
const plugins = currentOptions.expressionPlugins
|
||||
const options: BabelOptions = {
|
||||
plugins: plugins ? [...plugins, 'typescript'] : ['typescript']
|
||||
plugins: plugins ? [...plugins, 'typescript'] : ['typescript'],
|
||||
}
|
||||
if (parseMode === ExpParseMode.Statements) {
|
||||
// v-on with multi-inline-statements, pad 1 char
|
||||
|
@ -1003,7 +1003,7 @@ function createExp(
|
|||
|
||||
function emitError(code: ErrorCodes, index: number, message?: string) {
|
||||
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
|
||||
for (key in options) {
|
||||
if (options[key] != null) {
|
||||
// @ts-ignore
|
||||
// @ts-expect-error
|
||||
currentOptions[key] = options[key]
|
||||
}
|
||||
}
|
||||
|
@ -1036,11 +1036,11 @@ export function baseParse(input: string, options?: ParserOptions): RootNode {
|
|||
if (!__BROWSER__ && currentOptions.decodeEntities) {
|
||||
console.warn(
|
||||
`[@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) {
|
||||
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 RESOLVE_COMPONENT = Symbol(__DEV__ ? `resolveComponent` : ``)
|
||||
export const RESOLVE_DYNAMIC_COMPONENT = Symbol(
|
||||
__DEV__ ? `resolveDynamicComponent` : ``
|
||||
__DEV__ ? `resolveDynamicComponent` : ``,
|
||||
)
|
||||
export const RESOLVE_DIRECTIVE = Symbol(__DEV__ ? `resolveDirective` : ``)
|
||||
export const RESOLVE_FILTER = Symbol(__DEV__ ? `resolveFilter` : ``)
|
||||
|
@ -81,7 +81,7 @@ export const helperNameMap: Record<symbol, string> = {
|
|||
[UNREF]: `unref`,
|
||||
[IS_REF]: `isRef`,
|
||||
[WITH_MEMO]: `withMemo`,
|
||||
[IS_MEMO_SAME]: `isMemoSame`
|
||||
[IS_MEMO_SAME]: `isMemoSame`,
|
||||
}
|
||||
|
||||
export function registerRuntimeHelpers(helpers: Record<symbol, string>) {
|
||||
|
|
|
@ -23,7 +23,7 @@ IN THE SOFTWARE.
|
|||
*/
|
||||
|
||||
import { ErrorCodes } from './errors'
|
||||
import { ElementNode, Position } from './ast'
|
||||
import type { ElementNode, Position } from './ast'
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
import {
|
||||
EntityDecoder,
|
||||
DecodingMode,
|
||||
EntityDecoder,
|
||||
fromCodePoint,
|
||||
htmlDecodeTree,
|
||||
fromCodePoint
|
||||
} from 'entities/lib/decode.js'
|
||||
|
||||
export enum ParseMode {
|
||||
BASE,
|
||||
HTML,
|
||||
SFC
|
||||
SFC,
|
||||
}
|
||||
|
||||
export enum CharCodes {
|
||||
|
@ -77,7 +77,7 @@ export enum CharCodes {
|
|||
Colon = 0x3a, // ":"
|
||||
At = 0x40, // "@"
|
||||
LeftSquare = 91, // "["
|
||||
RightSquare = 93 // "]"
|
||||
RightSquare = 93, // "]"
|
||||
}
|
||||
|
||||
const defaultDelimitersOpen = new Uint8Array([123, 123]) // "{{"
|
||||
|
@ -134,7 +134,7 @@ export enum State {
|
|||
|
||||
InEntity,
|
||||
|
||||
InSFCRootTagName
|
||||
InSFCRootTagName,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -174,7 +174,7 @@ export enum QuoteType {
|
|||
NoValue = 0,
|
||||
Unquoted = 1,
|
||||
Single = 2,
|
||||
Double = 3
|
||||
Double = 3,
|
||||
}
|
||||
|
||||
export interface Callbacks {
|
||||
|
@ -221,8 +221,8 @@ export const Sequences = {
|
|||
StyleEnd: new Uint8Array([0x3c, 0x2f, 0x73, 0x74, 0x79, 0x6c, 0x65]), // `</style`
|
||||
TitleEnd: new Uint8Array([0x3c, 0x2f, 0x74, 0x69, 0x74, 0x6c, 0x65]), // `</title`
|
||||
TextareaEnd: new Uint8Array([
|
||||
0x3c, 0x2f, 116, 101, 120, 116, 97, 114, 101, 97
|
||||
]) // `</textarea
|
||||
0x3c, 0x2f, 116, 101, 120, 116, 97, 114, 101, 97,
|
||||
]), // `</textarea
|
||||
}
|
||||
|
||||
export default class Tokenizer {
|
||||
|
@ -256,11 +256,11 @@ export default class Tokenizer {
|
|||
|
||||
constructor(
|
||||
private readonly stack: ElementNode[],
|
||||
private readonly cbs: Callbacks
|
||||
private readonly cbs: Callbacks,
|
||||
) {
|
||||
if (!__BROWSER__) {
|
||||
this.entityDecoder = new EntityDecoder(htmlDecodeTree, (cp, consumed) =>
|
||||
this.emitCodePoint(cp, consumed)
|
||||
this.emitCodePoint(cp, consumed),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +299,7 @@ export default class Tokenizer {
|
|||
return {
|
||||
column,
|
||||
line,
|
||||
offset: index
|
||||
offset: index,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -647,7 +647,7 @@ export default class Tokenizer {
|
|||
if ((__DEV__ || !__BROWSER__) && c === CharCodes.Eq) {
|
||||
this.cbs.onerr(
|
||||
ErrorCodes.UNEXPECTED_EQUALS_SIGN_BEFORE_ATTRIBUTE_NAME,
|
||||
this.index
|
||||
this.index,
|
||||
)
|
||||
}
|
||||
this.handleAttrStart(c)
|
||||
|
@ -694,7 +694,7 @@ export default class Tokenizer {
|
|||
) {
|
||||
this.cbs.onerr(
|
||||
ErrorCodes.UNEXPECTED_CHARACTER_IN_ATTRIBUTE_NAME,
|
||||
this.index
|
||||
this.index,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -733,7 +733,7 @@ export default class Tokenizer {
|
|||
if (__DEV__ || !__BROWSER__) {
|
||||
this.cbs.onerr(
|
||||
ErrorCodes.X_MISSING_DYNAMIC_DIRECTIVE_ARGUMENT_END,
|
||||
this.index
|
||||
this.index,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -785,7 +785,7 @@ export default class Tokenizer {
|
|||
this.sectionStart = -1
|
||||
this.cbs.onattribend(
|
||||
quote === CharCodes.DoubleQuote ? QuoteType.Double : QuoteType.Single,
|
||||
this.index + 1
|
||||
this.index + 1,
|
||||
)
|
||||
this.state = State.BeforeAttrName
|
||||
} else if (!__BROWSER__ && c === CharCodes.Amp) {
|
||||
|
@ -814,7 +814,7 @@ export default class Tokenizer {
|
|||
) {
|
||||
this.cbs.onerr(
|
||||
ErrorCodes.UNEXPECTED_CHARACTER_IN_UNQUOTED_ATTRIBUTE_VALUE,
|
||||
this.index
|
||||
this.index,
|
||||
)
|
||||
} else if (!__BROWSER__ && c === CharCodes.Amp) {
|
||||
this.startEntity()
|
||||
|
@ -892,7 +892,7 @@ export default class Tokenizer {
|
|||
this.entityDecoder!.startEntity(
|
||||
this.baseState === State.Text || this.baseState === State.InRCDATA
|
||||
? DecodingMode.Legacy
|
||||
: DecodingMode.Attribute
|
||||
: DecodingMode.Attribute,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1156,7 +1156,7 @@ export default class Tokenizer {
|
|||
this.cbs.onattribentity(
|
||||
fromCodePoint(cp),
|
||||
this.entityStart,
|
||||
this.sectionStart
|
||||
this.sectionStart,
|
||||
)
|
||||
} else {
|
||||
if (this.sectionStart < this.entityStart) {
|
||||
|
@ -1168,7 +1168,7 @@ export default class Tokenizer {
|
|||
this.cbs.ontextentity(
|
||||
fromCodePoint(cp),
|
||||
this.entityStart,
|
||||
this.sectionStart
|
||||
this.sectionStart,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
import { TransformOptions } from './options'
|
||||
import type { TransformOptions } from './options'
|
||||
import {
|
||||
RootNode,
|
||||
NodeTypes,
|
||||
ParentNode,
|
||||
TemplateChildNode,
|
||||
ElementNode,
|
||||
DirectiveNode,
|
||||
Property,
|
||||
ExpressionNode,
|
||||
createSimpleExpression,
|
||||
JSChildNode,
|
||||
SimpleExpressionNode,
|
||||
ElementTypes,
|
||||
CacheExpression,
|
||||
createCacheExpression,
|
||||
TemplateLiteral,
|
||||
createVNodeCall,
|
||||
type ArrayExpression,
|
||||
type CacheExpression,
|
||||
ConstantTypes,
|
||||
ArrayExpression,
|
||||
convertToBlock
|
||||
type DirectiveNode,
|
||||
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'
|
||||
import {
|
||||
isString,
|
||||
isArray,
|
||||
NOOP,
|
||||
PatchFlags,
|
||||
PatchFlagNames,
|
||||
EMPTY_OBJ,
|
||||
NOOP,
|
||||
PatchFlagNames,
|
||||
PatchFlags,
|
||||
camelize,
|
||||
capitalize,
|
||||
camelize
|
||||
isArray,
|
||||
isString,
|
||||
} from '@vue/shared'
|
||||
import { defaultOnError, defaultOnWarn } from './errors'
|
||||
import {
|
||||
TO_DISPLAY_STRING,
|
||||
CREATE_COMMENT,
|
||||
FRAGMENT,
|
||||
TO_DISPLAY_STRING,
|
||||
helperNameMap,
|
||||
CREATE_COMMENT
|
||||
} from './runtimeHelpers'
|
||||
import { isVSlot } from './utils'
|
||||
import { hoistStatic, isSingleElementRoot } from './transforms/hoistStatic'
|
||||
import { CompilerCompatOptions } from './compat/compatConfig'
|
||||
import type { CompilerCompatOptions } from './compat/compatConfig'
|
||||
|
||||
// There are two types of transforms:
|
||||
//
|
||||
|
@ -48,7 +48,7 @@ import { CompilerCompatOptions } from './compat/compatConfig'
|
|||
// replace or remove the node being processed.
|
||||
export type NodeTransform = (
|
||||
node: RootNode | TemplateChildNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
) => void | (() => void) | (() => void)[]
|
||||
|
||||
// - DirectiveTransform:
|
||||
|
@ -60,7 +60,7 @@ export type DirectiveTransform = (
|
|||
context: TransformContext,
|
||||
// a platform specific compiler can import the base transform and augment
|
||||
// it by passing in this optional argument.
|
||||
augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult
|
||||
augmentor?: (ret: DirectiveTransformResult) => DirectiveTransformResult,
|
||||
) => DirectiveTransformResult
|
||||
|
||||
export interface DirectiveTransformResult {
|
||||
|
@ -74,7 +74,7 @@ export interface DirectiveTransformResult {
|
|||
export type StructuralDirectiveTransform = (
|
||||
node: ElementNode,
|
||||
dir: DirectiveNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
) => void | (() => void)
|
||||
|
||||
export interface ImportItem {
|
||||
|
@ -145,8 +145,8 @@ export function createTransformContext(
|
|||
isTS = false,
|
||||
onError = defaultOnError,
|
||||
onWarn = defaultOnWarn,
|
||||
compatConfig
|
||||
}: TransformOptions
|
||||
compatConfig,
|
||||
}: TransformOptions,
|
||||
): TransformContext {
|
||||
const nameMatch = filename.replace(/\?.*$/, '').match(/([^/\\]+)\.\w+$/)
|
||||
const context: TransformContext = {
|
||||
|
@ -190,7 +190,7 @@ export function createTransformContext(
|
|||
vFor: 0,
|
||||
vSlot: 0,
|
||||
vPre: 0,
|
||||
vOnce: 0
|
||||
vOnce: 0,
|
||||
},
|
||||
parent: null,
|
||||
currentNode: root,
|
||||
|
@ -287,14 +287,14 @@ export function createTransformContext(
|
|||
`_hoisted_${context.hoists.length}`,
|
||||
false,
|
||||
exp.loc,
|
||||
ConstantTypes.CAN_HOIST
|
||||
ConstantTypes.CAN_HOIST,
|
||||
)
|
||||
identifier.hoisted = exp
|
||||
return identifier
|
||||
},
|
||||
cache(exp, isVNode = false) {
|
||||
return createCacheExpression(context.cached++, exp, isVNode)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
if (__COMPAT__) {
|
||||
|
@ -383,7 +383,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
|
|||
undefined,
|
||||
true,
|
||||
undefined,
|
||||
false /* isComponent */
|
||||
false /* isComponent */,
|
||||
)
|
||||
} else {
|
||||
// no children = noop. codegen will return null.
|
||||
|
@ -392,7 +392,7 @@ function createRootCodegen(root: RootNode, context: TransformContext) {
|
|||
|
||||
export function traverseChildren(
|
||||
parent: ParentNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
) {
|
||||
let i = 0
|
||||
const nodeRemoved = () => {
|
||||
|
@ -410,7 +410,7 @@ export function traverseChildren(
|
|||
|
||||
export function traverseNode(
|
||||
node: RootNode | TemplateChildNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
) {
|
||||
context.currentNode = node
|
||||
// apply transform plugins
|
||||
|
@ -473,7 +473,7 @@ export function traverseNode(
|
|||
|
||||
export function createStructuralDirectiveTransform(
|
||||
name: string | RegExp,
|
||||
fn: StructuralDirectiveTransform
|
||||
fn: StructuralDirectiveTransform,
|
||||
): NodeTransform {
|
||||
const matches = isString(name)
|
||||
? (n: string) => n === name
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
import {
|
||||
type CallExpression,
|
||||
type ComponentNode,
|
||||
ConstantTypes,
|
||||
RootNode,
|
||||
NodeTypes,
|
||||
TemplateChildNode,
|
||||
SimpleExpressionNode,
|
||||
ElementTypes,
|
||||
PlainElementNode,
|
||||
ComponentNode,
|
||||
TemplateNode,
|
||||
VNodeCall,
|
||||
ParentNode,
|
||||
JSChildNode,
|
||||
CallExpression,
|
||||
type JSChildNode,
|
||||
NodeTypes,
|
||||
type ParentNode,
|
||||
type PlainElementNode,
|
||||
type RootNode,
|
||||
type SimpleExpressionNode,
|
||||
type TemplateChildNode,
|
||||
type TemplateNode,
|
||||
type VNodeCall,
|
||||
createArrayExpression,
|
||||
getVNodeBlockHelper,
|
||||
getVNodeHelper
|
||||
getVNodeHelper,
|
||||
} from '../ast'
|
||||
import { TransformContext } from '../transform'
|
||||
import { PatchFlags, isString, isSymbol, isArray } from '@vue/shared'
|
||||
import type { TransformContext } from '../transform'
|
||||
import { PatchFlags, isArray, isString, isSymbol } from '@vue/shared'
|
||||
import { isSlotOutlet } from '../utils'
|
||||
import {
|
||||
OPEN_BLOCK,
|
||||
GUARD_REACTIVE_PROPS,
|
||||
NORMALIZE_CLASS,
|
||||
NORMALIZE_PROPS,
|
||||
NORMALIZE_STYLE
|
||||
NORMALIZE_STYLE,
|
||||
OPEN_BLOCK,
|
||||
} from '../runtimeHelpers'
|
||||
|
||||
export function hoistStatic(root: RootNode, context: TransformContext) {
|
||||
|
@ -33,13 +33,13 @@ export function hoistStatic(root: RootNode, context: TransformContext) {
|
|||
context,
|
||||
// Root node is unfortunately non-hoistable due to potential parent
|
||||
// fallthrough attributes.
|
||||
isSingleElementRoot(root, root.children[0])
|
||||
isSingleElementRoot(root, root.children[0]),
|
||||
)
|
||||
}
|
||||
|
||||
export function isSingleElementRoot(
|
||||
root: RootNode,
|
||||
child: TemplateChildNode
|
||||
child: TemplateChildNode,
|
||||
): child is PlainElementNode | ComponentNode | TemplateNode {
|
||||
const { children } = root
|
||||
return (
|
||||
|
@ -52,7 +52,7 @@ export function isSingleElementRoot(
|
|||
function walk(
|
||||
node: ParentNode,
|
||||
context: TransformContext,
|
||||
doNotHoistNode: boolean = false
|
||||
doNotHoistNode: boolean = false,
|
||||
) {
|
||||
const { children } = node
|
||||
const originalCount = children.length
|
||||
|
@ -120,7 +120,7 @@ function walk(
|
|||
walk(
|
||||
child.branches[i],
|
||||
context,
|
||||
child.branches[i].children.length === 1
|
||||
child.branches[i].children.length === 1,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ function walk(
|
|||
isArray(node.codegenNode.children)
|
||||
) {
|
||||
const hoisted = context.hoist(
|
||||
createArrayExpression(node.codegenNode.children)
|
||||
createArrayExpression(node.codegenNode.children),
|
||||
)
|
||||
// #6978, #7138, #7114
|
||||
// a hoisted children array inside v-for can caused HMR errors since
|
||||
|
@ -155,7 +155,7 @@ function walk(
|
|||
|
||||
export function getConstantType(
|
||||
node: TemplateChildNode | SimpleExpressionNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): ConstantTypes {
|
||||
const { constantCache } = context
|
||||
switch (node.type) {
|
||||
|
@ -244,7 +244,7 @@ export function getConstantType(
|
|||
|
||||
context.removeHelper(OPEN_BLOCK)
|
||||
context.removeHelper(
|
||||
getVNodeBlockHelper(context.inSSR, codegenNode.isComponent)
|
||||
getVNodeBlockHelper(context.inSSR, codegenNode.isComponent),
|
||||
)
|
||||
codegenNode.isBlock = false
|
||||
context.helper(getVNodeHelper(context.inSSR, codegenNode.isComponent))
|
||||
|
@ -296,12 +296,12 @@ const allowHoistedHelperSet = new Set([
|
|||
NORMALIZE_CLASS,
|
||||
NORMALIZE_STYLE,
|
||||
NORMALIZE_PROPS,
|
||||
GUARD_REACTIVE_PROPS
|
||||
GUARD_REACTIVE_PROPS,
|
||||
])
|
||||
|
||||
function getConstantTypeOfHelperCall(
|
||||
value: CallExpression,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): ConstantTypes {
|
||||
if (
|
||||
value.type === NodeTypes.JS_CALL_EXPRESSION &&
|
||||
|
@ -321,7 +321,7 @@ function getConstantTypeOfHelperCall(
|
|||
|
||||
function getGeneratedPropsConstantType(
|
||||
node: PlainElementNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): ConstantTypes {
|
||||
let returnType = ConstantTypes.CAN_STRINGIFY
|
||||
const props = getNodeProps(node)
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
import { DirectiveTransform } from '../transform'
|
||||
import type { DirectiveTransform } from '../transform'
|
||||
|
||||
export const noopDirectiveTransform: DirectiveTransform = () => ({ props: [] })
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
import { NodeTransform, TransformContext } from '../transform'
|
||||
import type { NodeTransform, TransformContext } from '../transform'
|
||||
import {
|
||||
NodeTypes,
|
||||
type ArrayExpression,
|
||||
type CallExpression,
|
||||
type ComponentNode,
|
||||
ConstantTypes,
|
||||
type DirectiveArguments,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
CallExpression,
|
||||
ObjectExpression,
|
||||
ElementNode,
|
||||
DirectiveNode,
|
||||
ExpressionNode,
|
||||
ArrayExpression,
|
||||
createCallExpression,
|
||||
type ExpressionNode,
|
||||
type JSChildNode,
|
||||
NodeTypes,
|
||||
type ObjectExpression,
|
||||
type Property,
|
||||
type TemplateTextChildNode,
|
||||
type VNodeCall,
|
||||
createArrayExpression,
|
||||
createCallExpression,
|
||||
createObjectExpression,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
createObjectExpression,
|
||||
Property,
|
||||
ComponentNode,
|
||||
VNodeCall,
|
||||
TemplateTextChildNode,
|
||||
DirectiveArguments,
|
||||
createVNodeCall,
|
||||
ConstantTypes,
|
||||
JSChildNode
|
||||
} from '../ast'
|
||||
import {
|
||||
PatchFlags,
|
||||
PatchFlagNames,
|
||||
isSymbol,
|
||||
isOn,
|
||||
isObject,
|
||||
isReservedProp,
|
||||
capitalize,
|
||||
PatchFlags,
|
||||
camelize,
|
||||
isBuiltInDirective
|
||||
capitalize,
|
||||
isBuiltInDirective,
|
||||
isObject,
|
||||
isOn,
|
||||
isReservedProp,
|
||||
isSymbol,
|
||||
} from '@vue/shared'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import {
|
||||
RESOLVE_DIRECTIVE,
|
||||
RESOLVE_COMPONENT,
|
||||
RESOLVE_DYNAMIC_COMPONENT,
|
||||
GUARD_REACTIVE_PROPS,
|
||||
KEEP_ALIVE,
|
||||
MERGE_PROPS,
|
||||
NORMALIZE_CLASS,
|
||||
NORMALIZE_STYLE,
|
||||
NORMALIZE_PROPS,
|
||||
TO_HANDLERS,
|
||||
TELEPORT,
|
||||
KEEP_ALIVE,
|
||||
NORMALIZE_STYLE,
|
||||
RESOLVE_COMPONENT,
|
||||
RESOLVE_DIRECTIVE,
|
||||
RESOLVE_DYNAMIC_COMPONENT,
|
||||
SUSPENSE,
|
||||
TELEPORT,
|
||||
TO_HANDLERS,
|
||||
UNREF,
|
||||
GUARD_REACTIVE_PROPS
|
||||
} from '../runtimeHelpers'
|
||||
import {
|
||||
toValidAssetId,
|
||||
findProp,
|
||||
isCoreComponent,
|
||||
isStaticArgOf,
|
||||
isStaticExp
|
||||
isStaticExp,
|
||||
toValidAssetId,
|
||||
} from '../utils'
|
||||
import { buildSlots } from './vSlot'
|
||||
import { getConstantType } from './hoistStatic'
|
||||
import { BindingTypes } from '../options'
|
||||
import {
|
||||
checkCompatEnabled,
|
||||
CompilerDeprecationTypes,
|
||||
isCompatEnabled
|
||||
checkCompatEnabled,
|
||||
isCompatEnabled,
|
||||
} from '../compat/compatConfig'
|
||||
|
||||
// some directive transforms (e.g. v-model) may return a symbol for runtime
|
||||
|
@ -125,7 +125,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||
context,
|
||||
undefined,
|
||||
isComponent,
|
||||
isDynamicComponent
|
||||
isDynamicComponent,
|
||||
)
|
||||
vnodeProps = propsBuildResult.props
|
||||
patchFlag = propsBuildResult.patchFlag
|
||||
|
@ -134,7 +134,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||
vnodeDirectives =
|
||||
directives && directives.length
|
||||
? (createArrayExpression(
|
||||
directives.map(dir => buildDirectiveArgs(dir, context))
|
||||
directives.map(dir => buildDirectiveArgs(dir, context)),
|
||||
) as DirectiveArguments)
|
||||
: undefined
|
||||
|
||||
|
@ -160,8 +160,8 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||
createCompilerError(ErrorCodes.X_KEEP_ALIVE_INVALID_CHILDREN, {
|
||||
start: node.children[0].loc.start,
|
||||
end: node.children[node.children.length - 1].loc.end,
|
||||
source: ''
|
||||
})
|
||||
source: '',
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -239,7 +239,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||
!!shouldUseBlock,
|
||||
false /* disableTracking */,
|
||||
isComponent,
|
||||
node.loc
|
||||
node.loc,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -247,7 +247,7 @@ export const transformElement: NodeTransform = (node, context) => {
|
|||
export function resolveComponentType(
|
||||
node: ComponentNode,
|
||||
context: TransformContext,
|
||||
ssr = false
|
||||
ssr = false,
|
||||
) {
|
||||
let { tag } = node
|
||||
|
||||
|
@ -260,7 +260,7 @@ export function resolveComponentType(
|
|||
(__COMPAT__ &&
|
||||
isCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||
context
|
||||
context,
|
||||
))
|
||||
) {
|
||||
const exp =
|
||||
|
@ -269,7 +269,7 @@ export function resolveComponentType(
|
|||
: isProp.exp
|
||||
if (exp) {
|
||||
return createCallExpression(context.helper(RESOLVE_DYNAMIC_COMPONENT), [
|
||||
exp
|
||||
exp,
|
||||
])
|
||||
}
|
||||
} else if (
|
||||
|
@ -388,7 +388,7 @@ export function buildProps(
|
|||
props: ElementNode['props'] = node.props,
|
||||
isComponent: boolean,
|
||||
isDynamicComponent: boolean,
|
||||
ssr = false
|
||||
ssr = false,
|
||||
): {
|
||||
props: PropsExpression | undefined
|
||||
directives: DirectiveNode[]
|
||||
|
@ -416,7 +416,7 @@ export function buildProps(
|
|||
const pushMergeArg = (arg?: PropsExpression) => {
|
||||
if (properties.length) {
|
||||
mergeArgs.push(
|
||||
createObjectExpression(dedupeProperties(properties), elementLoc)
|
||||
createObjectExpression(dedupeProperties(properties), elementLoc),
|
||||
)
|
||||
properties = []
|
||||
}
|
||||
|
@ -496,8 +496,8 @@ export function buildProps(
|
|||
properties.push(
|
||||
createObjectProperty(
|
||||
createSimpleExpression('ref_for', true),
|
||||
createSimpleExpression('true')
|
||||
)
|
||||
createSimpleExpression('true'),
|
||||
),
|
||||
)
|
||||
}
|
||||
// in inline mode there is no setupState object, so we can't use string
|
||||
|
@ -514,8 +514,8 @@ export function buildProps(
|
|||
properties.push(
|
||||
createObjectProperty(
|
||||
createSimpleExpression('ref_key', true),
|
||||
createSimpleExpression(value.content, true, value.loc)
|
||||
)
|
||||
createSimpleExpression(value.content, true, value.loc),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -528,7 +528,7 @@ export function buildProps(
|
|||
(__COMPAT__ &&
|
||||
isCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||
context
|
||||
context,
|
||||
)))
|
||||
) {
|
||||
continue
|
||||
|
@ -539,9 +539,9 @@ export function buildProps(
|
|||
createSimpleExpression(
|
||||
value ? value.content : '',
|
||||
isStatic,
|
||||
value ? value.loc : loc
|
||||
)
|
||||
)
|
||||
value ? value.loc : loc,
|
||||
),
|
||||
),
|
||||
)
|
||||
} else {
|
||||
// directives
|
||||
|
@ -553,7 +553,7 @@ export function buildProps(
|
|||
if (name === 'slot') {
|
||||
if (!isComponent) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, loc)
|
||||
createCompilerError(ErrorCodes.X_V_SLOT_MISPLACED, loc),
|
||||
)
|
||||
}
|
||||
continue
|
||||
|
@ -571,7 +571,7 @@ export function buildProps(
|
|||
(__COMPAT__ &&
|
||||
isCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_IS_ON_ELEMENT,
|
||||
context
|
||||
context,
|
||||
))))
|
||||
) {
|
||||
continue
|
||||
|
@ -595,8 +595,8 @@ export function buildProps(
|
|||
properties.push(
|
||||
createObjectProperty(
|
||||
createSimpleExpression('ref_for', true),
|
||||
createSimpleExpression('true')
|
||||
)
|
||||
createSimpleExpression('true'),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -634,7 +634,7 @@ export function buildProps(
|
|||
checkCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,
|
||||
context,
|
||||
loc
|
||||
loc,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -642,7 +642,7 @@ export function buildProps(
|
|||
if (
|
||||
isCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_V_BIND_OBJECT_ORDER,
|
||||
context
|
||||
context,
|
||||
)
|
||||
) {
|
||||
mergeArgs.unshift(exp)
|
||||
|
@ -657,7 +657,7 @@ export function buildProps(
|
|||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
loc,
|
||||
callee: context.helper(TO_HANDLERS),
|
||||
arguments: isComponent ? [exp] : [exp, `true`]
|
||||
arguments: isComponent ? [exp] : [exp, `true`],
|
||||
})
|
||||
}
|
||||
} else {
|
||||
|
@ -666,8 +666,8 @@ export function buildProps(
|
|||
isVBind
|
||||
? ErrorCodes.X_V_BIND_NO_EXPRESSION
|
||||
: ErrorCodes.X_V_ON_NO_EXPRESSION,
|
||||
loc
|
||||
)
|
||||
loc,
|
||||
),
|
||||
)
|
||||
}
|
||||
continue
|
||||
|
@ -716,7 +716,7 @@ export function buildProps(
|
|||
propsExpression = createCallExpression(
|
||||
context.helper(MERGE_PROPS),
|
||||
mergeArgs,
|
||||
elementLoc
|
||||
elementLoc,
|
||||
)
|
||||
} else {
|
||||
// single v-bind with nothing else - no need for a mergeProps call
|
||||
|
@ -725,7 +725,7 @@ export function buildProps(
|
|||
} else if (properties.length) {
|
||||
propsExpression = createObjectExpression(
|
||||
dedupeProperties(properties),
|
||||
elementLoc
|
||||
elementLoc,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -785,7 +785,7 @@ export function buildProps(
|
|||
if (classProp && !isStaticExp(classProp.value)) {
|
||||
classProp.value = createCallExpression(
|
||||
context.helper(NORMALIZE_CLASS),
|
||||
[classProp.value]
|
||||
[classProp.value],
|
||||
)
|
||||
}
|
||||
if (
|
||||
|
@ -801,14 +801,14 @@ export function buildProps(
|
|||
) {
|
||||
styleProp.value = createCallExpression(
|
||||
context.helper(NORMALIZE_STYLE),
|
||||
[styleProp.value]
|
||||
[styleProp.value],
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// dynamic key binding, wrap with `normalizeProps`
|
||||
propsExpression = createCallExpression(
|
||||
context.helper(NORMALIZE_PROPS),
|
||||
[propsExpression]
|
||||
[propsExpression],
|
||||
)
|
||||
}
|
||||
break
|
||||
|
@ -821,9 +821,9 @@ export function buildProps(
|
|||
context.helper(NORMALIZE_PROPS),
|
||||
[
|
||||
createCallExpression(context.helper(GUARD_REACTIVE_PROPS), [
|
||||
propsExpression
|
||||
])
|
||||
]
|
||||
propsExpression,
|
||||
]),
|
||||
],
|
||||
)
|
||||
break
|
||||
}
|
||||
|
@ -834,7 +834,7 @@ export function buildProps(
|
|||
directives: runtimeDirectives,
|
||||
patchFlag,
|
||||
dynamicPropNames,
|
||||
shouldUseBlock
|
||||
shouldUseBlock,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -875,14 +875,14 @@ function mergeAsArray(existing: Property, incoming: Property) {
|
|||
} else {
|
||||
existing.value = createArrayExpression(
|
||||
[existing.value, incoming.value],
|
||||
existing.loc
|
||||
existing.loc,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function buildDirectiveArgs(
|
||||
dir: DirectiveNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): ArrayExpression {
|
||||
const dirArgs: ArrayExpression['elements'] = []
|
||||
const runtime = directiveImportMap.get(dir)
|
||||
|
@ -922,10 +922,10 @@ export function buildDirectiveArgs(
|
|||
dirArgs.push(
|
||||
createObjectExpression(
|
||||
dir.modifiers.map(modifier =>
|
||||
createObjectProperty(modifier, trueExpression)
|
||||
createObjectProperty(modifier, trueExpression),
|
||||
),
|
||||
loc
|
||||
)
|
||||
loc,
|
||||
),
|
||||
)
|
||||
}
|
||||
return createArrayExpression(dirArgs, dir.loc)
|
||||
|
|
|
@ -7,36 +7,36 @@
|
|||
// - 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
|
||||
// support and the code is wrapped in `with (this) { ... }`.
|
||||
import { NodeTransform, TransformContext } from '../transform'
|
||||
import type { NodeTransform, TransformContext } from '../transform'
|
||||
import {
|
||||
type CompoundExpressionNode,
|
||||
ConstantTypes,
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
createSimpleExpression,
|
||||
ExpressionNode,
|
||||
SimpleExpressionNode,
|
||||
CompoundExpressionNode,
|
||||
type SimpleExpressionNode,
|
||||
createCompoundExpression,
|
||||
ConstantTypes
|
||||
createSimpleExpression,
|
||||
} from '../ast'
|
||||
import {
|
||||
isInDestructureAssignment,
|
||||
isStaticProperty,
|
||||
isStaticPropertyKey,
|
||||
walkIdentifiers
|
||||
walkIdentifiers,
|
||||
} from '../babelUtils'
|
||||
import { advancePositionWithClone, isSimpleIdentifier } from '../utils'
|
||||
import {
|
||||
isGloballyAllowed,
|
||||
makeMap,
|
||||
genPropsAccessExp,
|
||||
hasOwn,
|
||||
isGloballyAllowed,
|
||||
isString,
|
||||
genPropsAccessExp
|
||||
makeMap,
|
||||
} from '@vue/shared'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import {
|
||||
Node,
|
||||
Identifier,
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import type {
|
||||
AssignmentExpression,
|
||||
UpdateExpression
|
||||
Identifier,
|
||||
Node,
|
||||
UpdateExpression,
|
||||
} from '@babel/types'
|
||||
import { validateBrowserExpression } from '../validateExpression'
|
||||
import { parse } from '@babel/parser'
|
||||
|
@ -53,7 +53,7 @@ export const transformExpression: NodeTransform = (node, context) => {
|
|||
if (node.type === NodeTypes.INTERPOLATION) {
|
||||
node.content = processExpression(
|
||||
node.content as SimpleExpressionNode,
|
||||
context
|
||||
context,
|
||||
)
|
||||
} else if (node.type === NodeTypes.ELEMENT) {
|
||||
// handle directives on element
|
||||
|
@ -74,7 +74,7 @@ export const transformExpression: NodeTransform = (node, context) => {
|
|||
exp,
|
||||
context,
|
||||
// slot args must be processed as function params
|
||||
dir.name === 'slot'
|
||||
dir.name === 'slot',
|
||||
)
|
||||
}
|
||||
if (arg && arg.type === NodeTypes.SIMPLE_EXPRESSION && !arg.isStatic) {
|
||||
|
@ -104,7 +104,7 @@ export function processExpression(
|
|||
asParams = false,
|
||||
// v-on handler values may contain multiple statements
|
||||
asRawStatements = false,
|
||||
localVars: Record<string, number> = Object.create(context.identifiers)
|
||||
localVars: Record<string, number> = Object.create(context.identifiers),
|
||||
): ExpressionNode {
|
||||
if (__BROWSER__) {
|
||||
if (__DEV__) {
|
||||
|
@ -163,8 +163,8 @@ export function processExpression(
|
|||
context,
|
||||
false,
|
||||
false,
|
||||
knownIds
|
||||
)
|
||||
knownIds,
|
||||
),
|
||||
)
|
||||
return `${context.helperString(IS_REF)}(${raw})${
|
||||
context.isTS ? ` //@ts-ignore\n` : ``
|
||||
|
@ -267,7 +267,7 @@ export function processExpression(
|
|||
: `(${rawExp})${asParams ? `=>{}` : ``}`
|
||||
try {
|
||||
ast = parse(source, {
|
||||
plugins: context.expressionPlugins
|
||||
plugins: context.expressionPlugins,
|
||||
}).program
|
||||
} catch (e: any) {
|
||||
context.onError(
|
||||
|
@ -275,8 +275,8 @@ export function processExpression(
|
|||
ErrorCodes.X_INVALID_EXPRESSION,
|
||||
node.loc,
|
||||
undefined,
|
||||
e.message
|
||||
)
|
||||
e.message,
|
||||
),
|
||||
)
|
||||
return node
|
||||
}
|
||||
|
@ -320,7 +320,7 @@ export function processExpression(
|
|||
},
|
||||
true, // invoke on ALL identifiers
|
||||
parentStack,
|
||||
knownIds
|
||||
knownIds,
|
||||
)
|
||||
|
||||
// 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),
|
||||
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) {
|
||||
children.push(rawExp.slice(end))
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
import { NodeTransform, TransformContext } from '../transform'
|
||||
import type { NodeTransform, TransformContext } from '../transform'
|
||||
import {
|
||||
type CallExpression,
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
CallExpression,
|
||||
type SlotOutletNode,
|
||||
createCallExpression,
|
||||
ExpressionNode,
|
||||
SlotOutletNode,
|
||||
createFunctionExpression
|
||||
createFunctionExpression,
|
||||
} from '../ast'
|
||||
import { isSlotOutlet, isStaticArgOf, isStaticExp } from '../utils'
|
||||
import { buildProps, PropsExpression } from './transformElement'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { type PropsExpression, buildProps } from './transformElement'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import { RENDER_SLOT } from '../runtimeHelpers'
|
||||
import { camelize } from '@vue/shared'
|
||||
|
||||
|
@ -23,7 +23,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||
slotName,
|
||||
'{}',
|
||||
'undefined',
|
||||
'true'
|
||||
'true',
|
||||
]
|
||||
let expectedLen = 2
|
||||
|
||||
|
@ -45,7 +45,7 @@ export const transformSlotOutlet: NodeTransform = (node, context) => {
|
|||
node.codegenNode = createCallExpression(
|
||||
context.helper(RENDER_SLOT),
|
||||
slotArgs,
|
||||
loc
|
||||
loc,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ interface SlotOutletProcessResult {
|
|||
|
||||
export function processSlotOutlet(
|
||||
node: SlotOutletNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): SlotOutletProcessResult {
|
||||
let slotName: string | ExpressionNode = `"default"`
|
||||
let slotProps: PropsExpression | undefined = undefined
|
||||
|
@ -92,7 +92,7 @@ export function processSlotOutlet(
|
|||
context,
|
||||
nonNameProps,
|
||||
false,
|
||||
false
|
||||
false,
|
||||
)
|
||||
slotProps = props
|
||||
|
||||
|
@ -100,14 +100,14 @@ export function processSlotOutlet(
|
|||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_SLOT_UNEXPECTED_DIRECTIVE_ON_SLOT_OUTLET,
|
||||
directives[0].loc
|
||||
)
|
||||
directives[0].loc,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
slotName,
|
||||
slotProps
|
||||
slotProps,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { NodeTransform } from '../transform'
|
||||
import type { NodeTransform } from '../transform'
|
||||
import {
|
||||
NodeTypes,
|
||||
CompoundExpressionNode,
|
||||
createCallExpression,
|
||||
CallExpression,
|
||||
ElementTypes,
|
||||
type CallExpression,
|
||||
type CompoundExpressionNode,
|
||||
ConstantTypes,
|
||||
createCompoundExpression
|
||||
ElementTypes,
|
||||
NodeTypes,
|
||||
createCallExpression,
|
||||
createCompoundExpression,
|
||||
} from '../ast'
|
||||
import { isText } from '../utils'
|
||||
import { CREATE_TEXT } from '../runtimeHelpers'
|
||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||
import { PatchFlagNames, PatchFlags } from '@vue/shared'
|
||||
import { getConstantType } from './hoistStatic'
|
||||
|
||||
// Merge adjacent text nodes and expressions into a single expression
|
||||
|
@ -39,7 +39,7 @@ export const transformText: NodeTransform = (node, context) => {
|
|||
if (!currentContainer) {
|
||||
currentContainer = children[i] = createCompoundExpression(
|
||||
[child],
|
||||
child.loc
|
||||
child.loc,
|
||||
)
|
||||
}
|
||||
// merge adjacent text node into current
|
||||
|
@ -72,7 +72,7 @@ export const transformText: NodeTransform = (node, context) => {
|
|||
!node.props.find(
|
||||
p =>
|
||||
p.type === NodeTypes.DIRECTIVE &&
|
||||
!context.directiveTransforms[p.name]
|
||||
!context.directiveTransforms[p.name],
|
||||
) &&
|
||||
// in compat mode, <template> tags with no special directives
|
||||
// will be rendered as a fragment so its children must be
|
||||
|
@ -100,7 +100,7 @@ export const transformText: NodeTransform = (node, context) => {
|
|||
) {
|
||||
callArgs.push(
|
||||
PatchFlags.TEXT +
|
||||
(__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.TEXT]} */` : ``)
|
||||
(__DEV__ ? ` /* ${PatchFlagNames[PatchFlags.TEXT]} */` : ``),
|
||||
)
|
||||
}
|
||||
children[i] = {
|
||||
|
@ -109,8 +109,8 @@ export const transformText: NodeTransform = (node, context) => {
|
|||
loc: child.loc,
|
||||
codegenNode: createCallExpression(
|
||||
context.helper(CREATE_TEXT),
|
||||
callArgs
|
||||
)
|
||||
callArgs,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { DirectiveTransform } from '../transform'
|
||||
import type { DirectiveTransform } from '../transform'
|
||||
import {
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
ExpressionNode,
|
||||
NodeTypes
|
||||
} from '../ast'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import { camelize } from '@vue/shared'
|
||||
import { CAMELIZE } from '../runtimeHelpers'
|
||||
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))
|
||||
return {
|
||||
props: [createObjectProperty(arg, createSimpleExpression('', true, loc))]
|
||||
props: [createObjectProperty(arg, createSimpleExpression('', true, loc))],
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
props: [createObjectProperty(arg, exp)]
|
||||
props: [createObjectProperty(arg, exp)],
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,52 +1,52 @@
|
|||
import {
|
||||
type TransformContext,
|
||||
createStructuralDirectiveTransform,
|
||||
TransformContext
|
||||
} from '../transform'
|
||||
import {
|
||||
type BlockCodegenNode,
|
||||
ConstantTypes,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
type ExpressionNode,
|
||||
type ForCodegenNode,
|
||||
type ForIteratorExpression,
|
||||
type ForNode,
|
||||
type ForParseResult,
|
||||
type ForRenderListExpression,
|
||||
NodeTypes,
|
||||
ExpressionNode,
|
||||
createSimpleExpression,
|
||||
SimpleExpressionNode,
|
||||
type PlainElementNode,
|
||||
type RenderSlotCall,
|
||||
type SimpleExpressionNode,
|
||||
type SlotOutletNode,
|
||||
type VNodeCall,
|
||||
createBlockStatement,
|
||||
createCallExpression,
|
||||
createCompoundExpression,
|
||||
createFunctionExpression,
|
||||
createObjectExpression,
|
||||
createObjectProperty,
|
||||
ForCodegenNode,
|
||||
RenderSlotCall,
|
||||
SlotOutletNode,
|
||||
ElementNode,
|
||||
DirectiveNode,
|
||||
ForNode,
|
||||
PlainElementNode,
|
||||
createSimpleExpression,
|
||||
createVNodeCall,
|
||||
VNodeCall,
|
||||
ForRenderListExpression,
|
||||
BlockCodegenNode,
|
||||
ForIteratorExpression,
|
||||
ConstantTypes,
|
||||
createBlockStatement,
|
||||
createCompoundExpression,
|
||||
getVNodeBlockHelper,
|
||||
getVNodeHelper,
|
||||
ForParseResult
|
||||
} from '../ast'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import {
|
||||
findDir,
|
||||
findProp,
|
||||
isTemplateNode,
|
||||
isSlotOutlet,
|
||||
injectProp,
|
||||
findDir
|
||||
isSlotOutlet,
|
||||
isTemplateNode,
|
||||
} from '../utils'
|
||||
import {
|
||||
RENDER_LIST,
|
||||
OPEN_BLOCK,
|
||||
FRAGMENT,
|
||||
IS_MEMO_SAME
|
||||
IS_MEMO_SAME,
|
||||
OPEN_BLOCK,
|
||||
RENDER_LIST,
|
||||
} from '../runtimeHelpers'
|
||||
import { processExpression } from './transformExpression'
|
||||
import { validateBrowserExpression } from '../validateExpression'
|
||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||
import { PatchFlagNames, PatchFlags } from '@vue/shared'
|
||||
|
||||
export const transformFor = createStructuralDirectiveTransform(
|
||||
'for',
|
||||
|
@ -56,7 +56,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
// create the loop render function expression now, and add the
|
||||
// iterator on exit after all children have been traversed
|
||||
const renderExp = createCallExpression(helper(RENDER_LIST), [
|
||||
forNode.source
|
||||
forNode.source,
|
||||
]) as ForRenderListExpression
|
||||
const isTemplate = isTemplateNode(node)
|
||||
const memo = findDir(node, 'memo')
|
||||
|
@ -76,13 +76,13 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
if (memo) {
|
||||
memo.exp = processExpression(
|
||||
memo.exp! as SimpleExpressionNode,
|
||||
context
|
||||
context,
|
||||
)
|
||||
}
|
||||
if (keyProperty && keyProp!.type !== NodeTypes.ATTRIBUTE) {
|
||||
keyProperty.value = processExpression(
|
||||
keyProperty.value as SimpleExpressionNode,
|
||||
context
|
||||
context,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
true /* isBlock */,
|
||||
!isStableFragment /* disableTracking */,
|
||||
false /* isComponent */,
|
||||
node.loc
|
||||
node.loc,
|
||||
) as ForCodegenNode
|
||||
|
||||
return () => {
|
||||
|
@ -125,8 +125,8 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_FOR_TEMPLATE_KEY_PLACEMENT,
|
||||
key.loc
|
||||
)
|
||||
key.loc,
|
||||
),
|
||||
)
|
||||
return true
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
undefined,
|
||||
true,
|
||||
undefined,
|
||||
false /* isComponent */
|
||||
false /* isComponent */,
|
||||
)
|
||||
} else {
|
||||
// Normal element v-for. Directly use the child's codegenNode
|
||||
|
@ -184,12 +184,12 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
// switch from block to vnode
|
||||
removeHelper(OPEN_BLOCK)
|
||||
removeHelper(
|
||||
getVNodeBlockHelper(context.inSSR, childBlock.isComponent)
|
||||
getVNodeBlockHelper(context.inSSR, childBlock.isComponent),
|
||||
)
|
||||
} else {
|
||||
// switch from vnode to block
|
||||
removeHelper(
|
||||
getVNodeHelper(context.inSSR, childBlock.isComponent)
|
||||
getVNodeHelper(context.inSSR, childBlock.isComponent),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -205,8 +205,8 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
if (memo) {
|
||||
const loop = createFunctionExpression(
|
||||
createForLoopParams(forNode.parseResult, [
|
||||
createSimpleExpression(`_cached`)
|
||||
])
|
||||
createSimpleExpression(`_cached`),
|
||||
]),
|
||||
)
|
||||
loop.body = createBlockStatement([
|
||||
createCompoundExpression([`const _memo = (`, memo.exp!, `)`]),
|
||||
|
@ -214,30 +214,30 @@ export const transformFor = createStructuralDirectiveTransform(
|
|||
`if (_cached`,
|
||||
...(keyExp ? [` && _cached.key === `, keyExp] : []),
|
||||
` && ${context.helperString(
|
||||
IS_MEMO_SAME
|
||||
)}(_cached, _memo)) return _cached`
|
||||
IS_MEMO_SAME,
|
||||
)}(_cached, _memo)) return _cached`,
|
||||
]),
|
||||
createCompoundExpression([`const _item = `, childBlock as any]),
|
||||
createSimpleExpression(`_item.memo = _memo`),
|
||||
createSimpleExpression(`return _item`)
|
||||
createSimpleExpression(`return _item`),
|
||||
])
|
||||
renderExp.arguments.push(
|
||||
loop as ForIteratorExpression,
|
||||
createSimpleExpression(`_cache`),
|
||||
createSimpleExpression(String(context.cached++))
|
||||
createSimpleExpression(String(context.cached++)),
|
||||
)
|
||||
} else {
|
||||
renderExp.arguments.push(
|
||||
createFunctionExpression(
|
||||
createForLoopParams(forNode.parseResult),
|
||||
childBlock,
|
||||
true /* force newline */
|
||||
) as ForIteratorExpression
|
||||
true /* force newline */,
|
||||
) as ForIteratorExpression,
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// target-agnostic transform used for both Client and SSR
|
||||
|
@ -245,11 +245,11 @@ export function processFor(
|
|||
node: ElementNode,
|
||||
dir: DirectiveNode,
|
||||
context: TransformContext,
|
||||
processCodegen?: (forNode: ForNode) => (() => void) | undefined
|
||||
processCodegen?: (forNode: ForNode) => (() => void) | undefined,
|
||||
) {
|
||||
if (!dir.exp) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc)
|
||||
createCompilerError(ErrorCodes.X_V_FOR_NO_EXPRESSION, dir.loc),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
@ -258,7 +258,7 @@ export function processFor(
|
|||
|
||||
if (!parseResult) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc)
|
||||
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, dir.loc),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
@ -276,7 +276,7 @@ export function processFor(
|
|||
keyAlias: key,
|
||||
objectIndexAlias: index,
|
||||
parseResult,
|
||||
children: isTemplateNode(node) ? node.children : [node]
|
||||
children: isTemplateNode(node) ? node.children : [node],
|
||||
}
|
||||
|
||||
context.replaceNode(forNode)
|
||||
|
@ -306,34 +306,34 @@ export function processFor(
|
|||
|
||||
export function finalizeForParseResult(
|
||||
result: ForParseResult,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
) {
|
||||
if (result.finalized) return
|
||||
|
||||
if (!__BROWSER__ && context.prefixIdentifiers) {
|
||||
result.source = processExpression(
|
||||
result.source as SimpleExpressionNode,
|
||||
context
|
||||
context,
|
||||
)
|
||||
if (result.key) {
|
||||
result.key = processExpression(
|
||||
result.key as SimpleExpressionNode,
|
||||
context,
|
||||
true
|
||||
true,
|
||||
)
|
||||
}
|
||||
if (result.index) {
|
||||
result.index = processExpression(
|
||||
result.index as SimpleExpressionNode,
|
||||
context,
|
||||
true
|
||||
true,
|
||||
)
|
||||
}
|
||||
if (result.value) {
|
||||
result.value = processExpression(
|
||||
result.value as SimpleExpressionNode,
|
||||
context,
|
||||
true
|
||||
true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -343,21 +343,21 @@ export function finalizeForParseResult(
|
|||
validateBrowserExpression(
|
||||
result.key as SimpleExpressionNode,
|
||||
context,
|
||||
true
|
||||
true,
|
||||
)
|
||||
}
|
||||
if (result.index) {
|
||||
validateBrowserExpression(
|
||||
result.index as SimpleExpressionNode,
|
||||
context,
|
||||
true
|
||||
true,
|
||||
)
|
||||
}
|
||||
if (result.value) {
|
||||
validateBrowserExpression(
|
||||
result.value as SimpleExpressionNode,
|
||||
context,
|
||||
true
|
||||
true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -366,13 +366,13 @@ export function finalizeForParseResult(
|
|||
|
||||
export function createForLoopParams(
|
||||
{ value, key, index }: ForParseResult,
|
||||
memoArgs: ExpressionNode[] = []
|
||||
memoArgs: ExpressionNode[] = [],
|
||||
): ExpressionNode[] {
|
||||
return createParamsList([value, key, index, ...memoArgs])
|
||||
}
|
||||
|
||||
function createParamsList(
|
||||
args: (ExpressionNode | undefined)[]
|
||||
args: (ExpressionNode | undefined)[],
|
||||
): ExpressionNode[] {
|
||||
let i = args.length
|
||||
while (i--) {
|
||||
|
|
|
@ -1,37 +1,37 @@
|
|||
import {
|
||||
type TransformContext,
|
||||
createStructuralDirectiveTransform,
|
||||
TransformContext,
|
||||
traverseNode
|
||||
traverseNode,
|
||||
} from '../transform'
|
||||
import {
|
||||
NodeTypes,
|
||||
type AttributeNode,
|
||||
type BlockCodegenNode,
|
||||
type CacheExpression,
|
||||
ConstantTypes,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
ElementNode,
|
||||
DirectiveNode,
|
||||
IfBranchNode,
|
||||
SimpleExpressionNode,
|
||||
type IfBranchNode,
|
||||
type IfConditionalExpression,
|
||||
type IfNode,
|
||||
type MemoExpression,
|
||||
NodeTypes,
|
||||
type SimpleExpressionNode,
|
||||
convertToBlock,
|
||||
createCallExpression,
|
||||
createConditionalExpression,
|
||||
createSimpleExpression,
|
||||
createObjectProperty,
|
||||
createObjectExpression,
|
||||
IfConditionalExpression,
|
||||
BlockCodegenNode,
|
||||
IfNode,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
createVNodeCall,
|
||||
AttributeNode,
|
||||
locStub,
|
||||
CacheExpression,
|
||||
ConstantTypes,
|
||||
MemoExpression,
|
||||
convertToBlock
|
||||
} from '../ast'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import { processExpression } from './transformExpression'
|
||||
import { validateBrowserExpression } from '../validateExpression'
|
||||
import { FRAGMENT, CREATE_COMMENT } from '../runtimeHelpers'
|
||||
import { injectProp, findDir, findProp, getMemoedVNodeCall } from '../utils'
|
||||
import { PatchFlags, PatchFlagNames } from '@vue/shared'
|
||||
import { CREATE_COMMENT, FRAGMENT } from '../runtimeHelpers'
|
||||
import { findDir, findProp, getMemoedVNodeCall, injectProp } from '../utils'
|
||||
import { PatchFlagNames, PatchFlags } from '@vue/shared'
|
||||
|
||||
export const transformIf = createStructuralDirectiveTransform(
|
||||
/^(if|else|else-if)$/,
|
||||
|
@ -57,7 +57,7 @@ export const transformIf = createStructuralDirectiveTransform(
|
|||
ifNode.codegenNode = createCodegenNodeForBranch(
|
||||
branch,
|
||||
key,
|
||||
context
|
||||
context,
|
||||
) as IfConditionalExpression
|
||||
} else {
|
||||
// attach this branch's codegen node to the v-if root.
|
||||
|
@ -65,12 +65,12 @@ export const transformIf = createStructuralDirectiveTransform(
|
|||
parentCondition.alternate = createCodegenNodeForBranch(
|
||||
branch,
|
||||
key + ifNode.branches.length - 1,
|
||||
context
|
||||
context,
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
// target-agnostic transform used for both Client and SSR
|
||||
|
@ -81,8 +81,8 @@ export function processIf(
|
|||
processCodegen?: (
|
||||
node: IfNode,
|
||||
branch: IfBranchNode,
|
||||
isRoot: boolean
|
||||
) => (() => void) | undefined
|
||||
isRoot: boolean,
|
||||
) => (() => void) | undefined,
|
||||
) {
|
||||
if (
|
||||
dir.name !== 'else' &&
|
||||
|
@ -90,7 +90,7 @@ export function processIf(
|
|||
) {
|
||||
const loc = dir.exp ? dir.exp.loc : node.loc
|
||||
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)
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ export function processIf(
|
|||
const ifNode: IfNode = {
|
||||
type: NodeTypes.IF,
|
||||
loc: node.loc,
|
||||
branches: [branch]
|
||||
branches: [branch],
|
||||
}
|
||||
context.replaceNode(ifNode)
|
||||
if (processCodegen) {
|
||||
|
@ -145,7 +145,7 @@ export function processIf(
|
|||
sibling.branches[sibling.branches.length - 1].condition === undefined
|
||||
) {
|
||||
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(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_IF_SAME_KEY,
|
||||
branch.userKey!.loc
|
||||
)
|
||||
branch.userKey!.loc,
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
|
@ -195,7 +195,7 @@ export function processIf(
|
|||
context.currentNode = null
|
||||
} else {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc)
|
||||
createCompilerError(ErrorCodes.X_V_ELSE_NO_ADJACENT_IF, node.loc),
|
||||
)
|
||||
}
|
||||
break
|
||||
|
@ -211,14 +211,14 @@ function createIfBranch(node: ElementNode, dir: DirectiveNode): IfBranchNode {
|
|||
condition: dir.name === 'else' ? undefined : dir.exp,
|
||||
children: isTemplateIf && !findDir(node, 'for') ? node.children : [node],
|
||||
userKey: findProp(node, `key`),
|
||||
isTemplateIf
|
||||
isTemplateIf,
|
||||
}
|
||||
}
|
||||
|
||||
function createCodegenNodeForBranch(
|
||||
branch: IfBranchNode,
|
||||
keyIndex: number,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): IfConditionalExpression | BlockCodegenNode | MemoExpression {
|
||||
if (branch.condition) {
|
||||
return createConditionalExpression(
|
||||
|
@ -228,8 +228,8 @@ function createCodegenNodeForBranch(
|
|||
// closes the current block.
|
||||
createCallExpression(context.helper(CREATE_COMMENT), [
|
||||
__DEV__ ? '"v-if"' : '""',
|
||||
'true'
|
||||
])
|
||||
'true',
|
||||
]),
|
||||
) as IfConditionalExpression
|
||||
} else {
|
||||
return createChildrenCodegenNode(branch, keyIndex, context)
|
||||
|
@ -239,7 +239,7 @@ function createCodegenNodeForBranch(
|
|||
function createChildrenCodegenNode(
|
||||
branch: IfBranchNode,
|
||||
keyIndex: number,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): BlockCodegenNode | MemoExpression {
|
||||
const { helper } = context
|
||||
const keyProperty = createObjectProperty(
|
||||
|
@ -248,8 +248,8 @@ function createChildrenCodegenNode(
|
|||
`${keyIndex}`,
|
||||
false,
|
||||
locStub,
|
||||
ConstantTypes.CAN_HOIST
|
||||
)
|
||||
ConstantTypes.CAN_HOIST,
|
||||
),
|
||||
)
|
||||
const { children } = branch
|
||||
const firstChild = children[0]
|
||||
|
@ -286,7 +286,7 @@ function createChildrenCodegenNode(
|
|||
true,
|
||||
false,
|
||||
false /* isComponent */,
|
||||
branch.loc
|
||||
branch.loc,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -306,7 +306,7 @@ function createChildrenCodegenNode(
|
|||
|
||||
function isSameKey(
|
||||
a: AttributeNode | DirectiveNode | undefined,
|
||||
b: AttributeNode | DirectiveNode
|
||||
b: AttributeNode | DirectiveNode,
|
||||
): boolean {
|
||||
if (!a || a.type !== b.type) {
|
||||
return false
|
||||
|
@ -334,7 +334,7 @@ function isSameKey(
|
|||
}
|
||||
|
||||
function getParentCondition(
|
||||
node: IfConditionalExpression | CacheExpression
|
||||
node: IfConditionalExpression | CacheExpression,
|
||||
): IfConditionalExpression {
|
||||
while (true) {
|
||||
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 {
|
||||
ElementTypes,
|
||||
type MemoExpression,
|
||||
NodeTypes,
|
||||
type PlainElementNode,
|
||||
convertToBlock,
|
||||
createCallExpression,
|
||||
createFunctionExpression,
|
||||
ElementTypes,
|
||||
MemoExpression,
|
||||
NodeTypes,
|
||||
PlainElementNode
|
||||
} from '../ast'
|
||||
import { WITH_MEMO } from '../runtimeHelpers'
|
||||
|
||||
|
@ -33,7 +33,7 @@ export const transformMemo: NodeTransform = (node, context) => {
|
|||
dir.exp!,
|
||||
createFunctionExpression(undefined, codegenNode),
|
||||
`_cache`,
|
||||
String(context.cached++)
|
||||
String(context.cached++),
|
||||
]) as MemoExpression
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import { DirectiveTransform } from '../transform'
|
||||
import type { DirectiveTransform } from '../transform'
|
||||
import {
|
||||
createSimpleExpression,
|
||||
createObjectProperty,
|
||||
createCompoundExpression,
|
||||
NodeTypes,
|
||||
Property,
|
||||
ConstantTypes,
|
||||
ElementTypes,
|
||||
ExpressionNode,
|
||||
ConstantTypes
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
type Property,
|
||||
createCompoundExpression,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
} from '../ast'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import {
|
||||
hasScopeRef,
|
||||
isMemberExpression,
|
||||
isSimpleIdentifier,
|
||||
hasScopeRef,
|
||||
isStaticExp
|
||||
isStaticExp,
|
||||
} from '../utils'
|
||||
import { IS_REF } from '../runtimeHelpers'
|
||||
import { BindingTypes } from '../options'
|
||||
|
@ -24,7 +24,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
const { exp, arg } = dir
|
||||
if (!exp) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_MODEL_NO_EXPRESSION, dir.loc)
|
||||
createCompilerError(ErrorCodes.X_V_MODEL_NO_EXPRESSION, dir.loc),
|
||||
)
|
||||
return createTransformProps()
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
(!isMemberExpression(expString, context) && !maybeRef)
|
||||
) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc)
|
||||
createCompilerError(ErrorCodes.X_V_MODEL_MALFORMED_EXPRESSION, exp.loc),
|
||||
)
|
||||
return createTransformProps()
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
context.identifiers[expString]
|
||||
) {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE, exp.loc)
|
||||
createCompilerError(ErrorCodes.X_V_MODEL_ON_SCOPE_VARIABLE, exp.loc),
|
||||
)
|
||||
return createTransformProps()
|
||||
}
|
||||
|
@ -92,7 +92,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
assignmentExp = createCompoundExpression([
|
||||
`${eventArg} => ((`,
|
||||
createSimpleExpression(rawExp, false, exp.loc),
|
||||
`).value = $event)`
|
||||
`).value = $event)`,
|
||||
])
|
||||
} else {
|
||||
// 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([
|
||||
`${eventArg} => (${context.helperString(IS_REF)}(${rawExp}) ? (`,
|
||||
createSimpleExpression(rawExp, false, exp.loc),
|
||||
`).value = $event : ${altAssignment})`
|
||||
`).value = $event : ${altAssignment})`,
|
||||
])
|
||||
}
|
||||
} else {
|
||||
assignmentExp = createCompoundExpression([
|
||||
`${eventArg} => ((`,
|
||||
exp,
|
||||
`) = $event)`
|
||||
`) = $event)`,
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -117,7 +117,7 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
// modelValue: foo
|
||||
createObjectProperty(propName, dir.exp!),
|
||||
// "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)
|
||||
|
@ -148,9 +148,9 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
`{ ${modifiers} }`,
|
||||
false,
|
||||
dir.loc,
|
||||
ConstantTypes.CAN_HOIST
|
||||
)
|
||||
)
|
||||
ConstantTypes.CAN_HOIST,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
import { DirectiveTransform, DirectiveTransformResult } from '../transform'
|
||||
import type { DirectiveTransform, DirectiveTransformResult } from '../transform'
|
||||
import {
|
||||
type DirectiveNode,
|
||||
ElementTypes,
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
type SimpleExpressionNode,
|
||||
createCompoundExpression,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
DirectiveNode,
|
||||
ElementTypes,
|
||||
ExpressionNode,
|
||||
NodeTypes,
|
||||
SimpleExpressionNode
|
||||
} from '../ast'
|
||||
import { camelize, toHandlerKey } from '@vue/shared'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import { processExpression } from './transformExpression'
|
||||
import { validateBrowserExpression } from '../validateExpression'
|
||||
import { hasScopeRef, isMemberExpression } from '../utils'
|
||||
|
@ -33,7 +33,7 @@ export const transformOn: DirectiveTransform = (
|
|||
dir,
|
||||
node,
|
||||
context,
|
||||
augmentor
|
||||
augmentor,
|
||||
) => {
|
||||
const { loc, modifiers, arg } = dir as VOnDirectiveNode
|
||||
if (!dir.exp && !modifiers.length) {
|
||||
|
@ -65,7 +65,7 @@ export const transformOn: DirectiveTransform = (
|
|||
eventName = createCompoundExpression([
|
||||
`${context.helperString(TO_HANDLER_KEY)}(`,
|
||||
arg,
|
||||
`)`
|
||||
`)`,
|
||||
])
|
||||
}
|
||||
} else {
|
||||
|
@ -95,7 +95,7 @@ export const transformOn: DirectiveTransform = (
|
|||
exp,
|
||||
context,
|
||||
false,
|
||||
hasMultipleStatements
|
||||
hasMultipleStatements,
|
||||
)
|
||||
isInlineStatement && context.removeIdentifiers(`$event`)
|
||||
// with scope analysis, the function is hoistable if it has no reference
|
||||
|
@ -134,7 +134,7 @@ export const transformOn: DirectiveTransform = (
|
|||
exp as SimpleExpressionNode,
|
||||
context,
|
||||
false,
|
||||
hasMultipleStatements
|
||||
hasMultipleStatements,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,7 @@ export const transformOn: DirectiveTransform = (
|
|||
}(...args)`
|
||||
} => ${hasMultipleStatements ? `{` : `(`}`,
|
||||
exp,
|
||||
hasMultipleStatements ? `}` : `)`
|
||||
hasMultipleStatements ? `}` : `)`,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
@ -160,9 +160,9 @@ export const transformOn: DirectiveTransform = (
|
|||
props: [
|
||||
createObjectProperty(
|
||||
eventName,
|
||||
exp || createSimpleExpression(`() => {}`, false, loc)
|
||||
)
|
||||
]
|
||||
exp || createSimpleExpression(`() => {}`, false, loc),
|
||||
),
|
||||
],
|
||||
}
|
||||
|
||||
// apply extended compiler augmentor
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { NodeTransform } from '../transform'
|
||||
import type { NodeTransform } from '../transform'
|
||||
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'
|
||||
|
||||
const seen = new WeakSet()
|
||||
|
|
|
@ -1,34 +1,34 @@
|
|||
import {
|
||||
ElementNode,
|
||||
ObjectExpression,
|
||||
createObjectExpression,
|
||||
type CallExpression,
|
||||
type ConditionalExpression,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
type ExpressionNode,
|
||||
type FunctionExpression,
|
||||
NodeTypes,
|
||||
type ObjectExpression,
|
||||
type Property,
|
||||
type SlotsExpression,
|
||||
type SourceLocation,
|
||||
type TemplateChildNode,
|
||||
createArrayExpression,
|
||||
createCallExpression,
|
||||
createConditionalExpression,
|
||||
createFunctionExpression,
|
||||
createObjectExpression,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
createFunctionExpression,
|
||||
DirectiveNode,
|
||||
ElementTypes,
|
||||
ExpressionNode,
|
||||
Property,
|
||||
TemplateChildNode,
|
||||
SourceLocation,
|
||||
createConditionalExpression,
|
||||
ConditionalExpression,
|
||||
FunctionExpression,
|
||||
CallExpression,
|
||||
createCallExpression,
|
||||
createArrayExpression,
|
||||
SlotsExpression
|
||||
} from '../ast'
|
||||
import { TransformContext, NodeTransform } from '../transform'
|
||||
import { createCompilerError, ErrorCodes } from '../errors'
|
||||
import type { NodeTransform, TransformContext } from '../transform'
|
||||
import { ErrorCodes, createCompilerError } from '../errors'
|
||||
import {
|
||||
findDir,
|
||||
isTemplateNode,
|
||||
assert,
|
||||
isVSlot,
|
||||
findDir,
|
||||
hasScopeRef,
|
||||
isStaticExp
|
||||
isStaticExp,
|
||||
isTemplateNode,
|
||||
isVSlot,
|
||||
} from '../utils'
|
||||
import { CREATE_SLOTS, RENDER_LIST, WITH_CTX } from '../runtimeHelpers'
|
||||
import { createForLoopParams, finalizeForParseResult } from './vFor'
|
||||
|
@ -99,7 +99,7 @@ export type SlotFnBuilder = (
|
|||
slotProps: ExpressionNode | undefined,
|
||||
vFor: DirectiveNode | undefined,
|
||||
slotChildren: TemplateChildNode[],
|
||||
loc: SourceLocation
|
||||
loc: SourceLocation,
|
||||
) => FunctionExpression
|
||||
|
||||
const buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>
|
||||
|
@ -108,7 +108,7 @@ const buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>
|
|||
children,
|
||||
false /* newline */,
|
||||
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
|
||||
|
@ -116,7 +116,7 @@ const buildClientSlotFn: SlotFnBuilder = (props, _vForExp, children, loc) =>
|
|||
export function buildSlots(
|
||||
node: ElementNode,
|
||||
context: TransformContext,
|
||||
buildSlotFn: SlotFnBuilder = buildClientSlotFn
|
||||
buildSlotFn: SlotFnBuilder = buildClientSlotFn,
|
||||
): {
|
||||
slots: SlotsExpression
|
||||
hasDynamicSlots: boolean
|
||||
|
@ -147,8 +147,8 @@ export function buildSlots(
|
|||
slotsProperties.push(
|
||||
createObjectProperty(
|
||||
arg || createSimpleExpression('default', true),
|
||||
buildSlotFn(exp, undefined, children, loc)
|
||||
)
|
||||
buildSlotFn(exp, undefined, children, loc),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ export function buildSlots(
|
|||
if (onComponentSlot) {
|
||||
// already has on-component slot - this is incorrect usage.
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc)
|
||||
createCompilerError(ErrorCodes.X_V_SLOT_MIXED_SLOT_USAGE, slotDir.loc),
|
||||
)
|
||||
break
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ export function buildSlots(
|
|||
const {
|
||||
arg: slotName = createSimpleExpression(`default`, true),
|
||||
exp: slotProps,
|
||||
loc: dirLoc
|
||||
loc: dirLoc,
|
||||
} = slotDir
|
||||
|
||||
// check if name is dynamic.
|
||||
|
@ -211,8 +211,8 @@ export function buildSlots(
|
|||
createConditionalExpression(
|
||||
vIf.exp!,
|
||||
buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++),
|
||||
defaultFallback
|
||||
)
|
||||
defaultFallback,
|
||||
),
|
||||
)
|
||||
} else if (
|
||||
(vElse = findDir(slotElement, /^else(-if)?$/, true /* allowEmpty */))
|
||||
|
@ -246,14 +246,14 @@ export function buildSlots(
|
|||
buildDynamicSlot(
|
||||
slotName,
|
||||
slotFunction,
|
||||
conditionalBranchIndex++
|
||||
conditionalBranchIndex++,
|
||||
),
|
||||
defaultFallback
|
||||
defaultFallback,
|
||||
)
|
||||
: buildDynamicSlot(slotName, slotFunction, conditionalBranchIndex++)
|
||||
} else {
|
||||
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) {
|
||||
|
@ -269,13 +269,16 @@ export function buildSlots(
|
|||
createFunctionExpression(
|
||||
createForLoopParams(parseResult),
|
||||
buildDynamicSlot(slotName, slotFunction),
|
||||
true /* force newline */
|
||||
)
|
||||
])
|
||||
true /* force newline */,
|
||||
),
|
||||
]),
|
||||
)
|
||||
} else {
|
||||
context.onError(
|
||||
createCompilerError(ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION, vFor.loc)
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_FOR_MALFORMED_EXPRESSION,
|
||||
vFor.loc,
|
||||
),
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -285,8 +288,8 @@ export function buildSlots(
|
|||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_SLOT_DUPLICATE_SLOT_NAMES,
|
||||
dirLoc
|
||||
)
|
||||
dirLoc,
|
||||
),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
@ -302,7 +305,7 @@ export function buildSlots(
|
|||
if (!onComponentSlot) {
|
||||
const buildDefaultSlotProperty = (
|
||||
props: ExpressionNode | undefined,
|
||||
children: TemplateChildNode[]
|
||||
children: TemplateChildNode[],
|
||||
) => {
|
||||
const fn = buildSlotFn(props, undefined, children, loc)
|
||||
if (__COMPAT__ && context.compatConfig) {
|
||||
|
@ -326,12 +329,12 @@ export function buildSlots(
|
|||
context.onError(
|
||||
createCompilerError(
|
||||
ErrorCodes.X_V_SLOT_EXTRANEOUS_DEFAULT_SLOT_CHILDREN,
|
||||
implicitDefaultChildren[0].loc
|
||||
)
|
||||
implicitDefaultChildren[0].loc,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
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
|
||||
createSimpleExpression(
|
||||
slotFlag + (__DEV__ ? ` /* ${slotFlagsText[slotFlag]} */` : ``),
|
||||
false
|
||||
)
|
||||
)
|
||||
false,
|
||||
),
|
||||
),
|
||||
),
|
||||
loc
|
||||
loc,
|
||||
) as SlotsExpression
|
||||
if (dynamicSlots.length) {
|
||||
slots = createCallExpression(context.helper(CREATE_SLOTS), [
|
||||
slots,
|
||||
createArrayExpression(dynamicSlots)
|
||||
createArrayExpression(dynamicSlots),
|
||||
]) as SlotsExpression
|
||||
}
|
||||
|
||||
return {
|
||||
slots,
|
||||
hasDynamicSlots
|
||||
hasDynamicSlots,
|
||||
}
|
||||
}
|
||||
|
||||
function buildDynamicSlot(
|
||||
name: ExpressionNode,
|
||||
fn: FunctionExpression,
|
||||
index?: number
|
||||
index?: number,
|
||||
): ObjectExpression {
|
||||
const props = [
|
||||
createObjectProperty(`name`, name),
|
||||
createObjectProperty(`fn`, fn)
|
||||
createObjectProperty(`fn`, fn),
|
||||
]
|
||||
if (index != null) {
|
||||
props.push(
|
||||
createObjectProperty(`key`, createSimpleExpression(String(index), true))
|
||||
createObjectProperty(`key`, createSimpleExpression(String(index), true)),
|
||||
)
|
||||
}
|
||||
return createObjectExpression(props)
|
||||
|
|
|
@ -1,45 +1,45 @@
|
|||
import {
|
||||
Position,
|
||||
ElementNode,
|
||||
NodeTypes,
|
||||
CallExpression,
|
||||
createCallExpression,
|
||||
DirectiveNode,
|
||||
type BlockCodegenNode,
|
||||
type CallExpression,
|
||||
type DirectiveNode,
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
TemplateChildNode,
|
||||
RootNode,
|
||||
ObjectExpression,
|
||||
Property,
|
||||
JSChildNode,
|
||||
type ExpressionNode,
|
||||
type IfBranchNode,
|
||||
type InterpolationNode,
|
||||
type 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,
|
||||
SlotOutletNode,
|
||||
TemplateNode,
|
||||
RenderSlotCall,
|
||||
ExpressionNode,
|
||||
IfBranchNode,
|
||||
TextNode,
|
||||
InterpolationNode,
|
||||
VNodeCall,
|
||||
SimpleExpressionNode,
|
||||
BlockCodegenNode,
|
||||
MemoExpression
|
||||
} from './ast'
|
||||
import { TransformContext } from './transform'
|
||||
import type { TransformContext } from './transform'
|
||||
import {
|
||||
MERGE_PROPS,
|
||||
TELEPORT,
|
||||
SUSPENSE,
|
||||
KEEP_ALIVE,
|
||||
BASE_TRANSITION,
|
||||
TO_HANDLERS,
|
||||
NORMALIZE_PROPS,
|
||||
GUARD_REACTIVE_PROPS,
|
||||
WITH_MEMO
|
||||
KEEP_ALIVE,
|
||||
MERGE_PROPS,
|
||||
NORMALIZE_PROPS,
|
||||
SUSPENSE,
|
||||
TELEPORT,
|
||||
TO_HANDLERS,
|
||||
WITH_MEMO,
|
||||
} from './runtimeHelpers'
|
||||
import { isString, isObject, NOOP } from '@vue/shared'
|
||||
import { PropsExpression } from './transforms/transformElement'
|
||||
import { NOOP, isObject, isString } from '@vue/shared'
|
||||
import type { PropsExpression } from './transforms/transformElement'
|
||||
import { parseExpression } from '@babel/parser'
|
||||
import { Expression } from '@babel/types'
|
||||
import type { Expression } from '@babel/types'
|
||||
import { unwrapTSNode } from './babelUtils'
|
||||
|
||||
export const isStaticExp = (p: JSChildNode): p is SimpleExpressionNode =>
|
||||
|
@ -70,7 +70,7 @@ enum MemberExpLexState {
|
|||
inMemberExp,
|
||||
inBrackets,
|
||||
inParens,
|
||||
inString
|
||||
inString,
|
||||
}
|
||||
|
||||
const validFirstIdentCharRE = /[A-Za-z_$\xA0-\uFFFF]/
|
||||
|
@ -157,7 +157,7 @@ export const isMemberExpressionNode = __BROWSER__
|
|||
: (path: string, context: TransformContext): boolean => {
|
||||
try {
|
||||
let ret: Expression = parseExpression(path, {
|
||||
plugins: context.expressionPlugins
|
||||
plugins: context.expressionPlugins,
|
||||
})
|
||||
ret = unwrapTSNode(ret) as Expression
|
||||
return (
|
||||
|
@ -177,16 +177,16 @@ export const isMemberExpression = __BROWSER__
|
|||
export function advancePositionWithClone(
|
||||
pos: Position,
|
||||
source: string,
|
||||
numberOfCharacters: number = source.length
|
||||
numberOfCharacters: number = source.length,
|
||||
): Position {
|
||||
return advancePositionWithMutation(
|
||||
{
|
||||
offset: pos.offset,
|
||||
line: pos.line,
|
||||
column: pos.column
|
||||
column: pos.column,
|
||||
},
|
||||
source,
|
||||
numberOfCharacters
|
||||
numberOfCharacters,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ export function advancePositionWithClone(
|
|||
export function advancePositionWithMutation(
|
||||
pos: Position,
|
||||
source: string,
|
||||
numberOfCharacters: number = source.length
|
||||
numberOfCharacters: number = source.length,
|
||||
): Position {
|
||||
let linesCount = 0
|
||||
let lastNewLinePos = -1
|
||||
|
@ -226,7 +226,7 @@ export function assert(condition: boolean, msg?: string) {
|
|||
export function findDir(
|
||||
node: ElementNode,
|
||||
name: string | RegExp,
|
||||
allowEmpty: boolean = false
|
||||
allowEmpty: boolean = false,
|
||||
): DirectiveNode | undefined {
|
||||
for (let i = 0; i < node.props.length; i++) {
|
||||
const p = node.props[i]
|
||||
|
@ -244,7 +244,7 @@ export function findProp(
|
|||
node: ElementNode,
|
||||
name: string,
|
||||
dynamicOnly: boolean = false,
|
||||
allowEmpty: boolean = false
|
||||
allowEmpty: boolean = false,
|
||||
): ElementNode['props'][0] | undefined {
|
||||
for (let i = 0; i < node.props.length; i++) {
|
||||
const p = node.props[i]
|
||||
|
@ -265,7 +265,7 @@ export function findProp(
|
|||
|
||||
export function isStaticArgOf(
|
||||
arg: DirectiveNode['arg'],
|
||||
name: string
|
||||
name: string,
|
||||
): boolean {
|
||||
return !!(arg && isStaticExp(arg) && arg.content === name)
|
||||
}
|
||||
|
@ -277,12 +277,12 @@ export function hasDynamicKeyVBind(node: ElementNode): boolean {
|
|||
p.name === 'bind' &&
|
||||
(!p.arg || // v-bind="obj"
|
||||
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(
|
||||
node: TemplateChildNode
|
||||
node: TemplateChildNode,
|
||||
): node is TextNode | InterpolationNode {
|
||||
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(
|
||||
node: RootNode | TemplateChildNode
|
||||
node: RootNode | TemplateChildNode,
|
||||
): node is TemplateNode {
|
||||
return (
|
||||
node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.TEMPLATE
|
||||
|
@ -300,7 +300,7 @@ export function isTemplateNode(
|
|||
}
|
||||
|
||||
export function isSlotOutlet(
|
||||
node: RootNode | TemplateChildNode
|
||||
node: RootNode | TemplateChildNode,
|
||||
): node is SlotOutletNode {
|
||||
return node.type === NodeTypes.ELEMENT && node.tagType === ElementTypes.SLOT
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ const propsHelperSet = new Set([NORMALIZE_PROPS, GUARD_REACTIVE_PROPS])
|
|||
|
||||
function getUnnormalizedProps(
|
||||
props: PropsExpression | '{}',
|
||||
callPath: CallExpression[] = []
|
||||
callPath: CallExpression[] = [],
|
||||
): [PropsExpression | '{}', CallExpression[]] {
|
||||
if (
|
||||
props &&
|
||||
|
@ -320,7 +320,7 @@ function getUnnormalizedProps(
|
|||
if (!isString(callee) && propsHelperSet.has(callee)) {
|
||||
return getUnnormalizedProps(
|
||||
props.arguments[0] as PropsExpression,
|
||||
callPath.concat(props)
|
||||
callPath.concat(props),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +329,7 @@ function getUnnormalizedProps(
|
|||
export function injectProp(
|
||||
node: VNodeCall | RenderSlotCall,
|
||||
prop: Property,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
) {
|
||||
let propsWithInjection: ObjectExpression | CallExpression | undefined
|
||||
/**
|
||||
|
@ -372,7 +372,7 @@ export function injectProp(
|
|||
// #2366
|
||||
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
|
||||
createObjectExpression([prop]),
|
||||
props
|
||||
props,
|
||||
])
|
||||
} else {
|
||||
props.arguments.unshift(createObjectExpression([prop]))
|
||||
|
@ -388,7 +388,7 @@ export function injectProp(
|
|||
// single v-bind with expression, return a merged replacement
|
||||
propsWithInjection = createCallExpression(context.helper(MERGE_PROPS), [
|
||||
createObjectExpression([prop]),
|
||||
props
|
||||
props,
|
||||
])
|
||||
// in the case of nested helper call, e.g. `normalizeProps(guardReactiveProps(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(
|
||||
p =>
|
||||
p.key.type === NodeTypes.SIMPLE_EXPRESSION &&
|
||||
p.key.content === propKeyName
|
||||
p.key.content === propKeyName,
|
||||
)
|
||||
}
|
||||
return result
|
||||
|
@ -428,7 +428,7 @@ function hasProp(prop: Property, props: ObjectExpression) {
|
|||
|
||||
export function toValidAssetId(
|
||||
name: string,
|
||||
type: 'component' | 'directive' | 'filter'
|
||||
type: 'component' | 'directive' | 'filter',
|
||||
): string {
|
||||
// see issue#4422, we need adding identifier on validAssetId if variable `name` has specific character
|
||||
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
|
||||
export function hasScopeRef(
|
||||
node: TemplateChildNode | IfBranchNode | ExpressionNode | undefined,
|
||||
ids: TransformContext['identifiers']
|
||||
ids: TransformContext['identifiers'],
|
||||
): boolean {
|
||||
if (!node || Object.keys(ids).length === 0) {
|
||||
return false
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { SimpleExpressionNode } from './ast'
|
||||
import { TransformContext } from './transform'
|
||||
import { createCompilerError, ErrorCodes } from './errors'
|
||||
import type { SimpleExpressionNode } from './ast'
|
||||
import type { TransformContext } from './transform'
|
||||
import { ErrorCodes, createCompilerError } from './errors'
|
||||
|
||||
// these keywords should not appear inside expressions, but operators like
|
||||
// 'typeof', 'instanceof', and 'in' are allowed
|
||||
|
@ -13,7 +13,7 @@ const prohibitedKeywordRE = new RegExp(
|
|||
)
|
||||
.split(',')
|
||||
.join('\\b|\\b') +
|
||||
'\\b'
|
||||
'\\b',
|
||||
)
|
||||
|
||||
// strip strings in expressions
|
||||
|
@ -29,7 +29,7 @@ export function validateBrowserExpression(
|
|||
node: SimpleExpressionNode,
|
||||
context: TransformContext,
|
||||
asParams = false,
|
||||
asRawStatements = false
|
||||
asRawStatements = false,
|
||||
) {
|
||||
const exp = node.content
|
||||
|
||||
|
@ -43,7 +43,7 @@ export function validateBrowserExpression(
|
|||
new Function(
|
||||
asRawStatements
|
||||
? ` ${exp} `
|
||||
: `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`
|
||||
: `return ${asParams ? `(${exp}) => {}` : `(${exp})`}`,
|
||||
)
|
||||
} catch (e: any) {
|
||||
let message = e.message
|
||||
|
@ -58,8 +58,8 @@ export function validateBrowserExpression(
|
|||
ErrorCodes.X_INVALID_EXPRESSION,
|
||||
node.loc,
|
||||
undefined,
|
||||
message
|
||||
)
|
||||
message,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,16 +29,16 @@ describe('decodeHtmlBrowser', () => {
|
|||
|
||||
// #3001 html tags inside attribute values
|
||||
expect(decodeHtmlBrowser('<strong>Text</strong>', true)).toBe(
|
||||
'<strong>Text</strong>'
|
||||
'<strong>Text</strong>',
|
||||
)
|
||||
expect(decodeHtmlBrowser('<strong>&</strong>', true)).toBe(
|
||||
'<strong>&</strong>'
|
||||
'<strong>&</strong>',
|
||||
)
|
||||
expect(
|
||||
decodeHtmlBrowser(
|
||||
'<strong><strong>&</strong></strong>',
|
||||
true
|
||||
)
|
||||
true,
|
||||
),
|
||||
).toBe('<strong><strong>&</strong></strong>')
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import {
|
||||
baseParse as parse,
|
||||
NodeTypes,
|
||||
ElementNode,
|
||||
TextNode,
|
||||
ElementTypes,
|
||||
InterpolationNode,
|
||||
AttributeNode,
|
||||
type AttributeNode,
|
||||
ConstantTypes,
|
||||
Namespaces
|
||||
type ElementNode,
|
||||
ElementTypes,
|
||||
type InterpolationNode,
|
||||
Namespaces,
|
||||
NodeTypes,
|
||||
type TextNode,
|
||||
baseParse as parse,
|
||||
} from '@vue/compiler-core'
|
||||
import { parserOptions } from '../src/parserOptions'
|
||||
|
||||
|
@ -16,7 +16,7 @@ describe('DOM parser', () => {
|
|||
test('textarea handles comments/elements as just text', () => {
|
||||
const ast = parse(
|
||||
'<textarea>some<div>text</div>and<!--comment--></textarea>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const element = ast.children[0] as ElementNode
|
||||
const text = element.children[0] as TextNode
|
||||
|
@ -27,8 +27,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 10, line: 1, column: 11 },
|
||||
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: {
|
||||
start: { offset: 10, line: 1, column: 11 },
|
||||
end: { offset: 15, line: 1, column: 16 },
|
||||
source: '&'
|
||||
}
|
||||
source: '&',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -58,16 +58,16 @@ describe('DOM parser', () => {
|
|||
content: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `foo`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
test('style handles comments/elements as just a text', () => {
|
||||
const ast = parse(
|
||||
'<style>some<div>text</div>and<!--comment--></style>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const element = ast.children[0] as ElementNode
|
||||
const text = element.children[0] as TextNode
|
||||
|
@ -78,8 +78,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 7, line: 1, column: 8 },
|
||||
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: {
|
||||
start: { offset: 7, line: 1, column: 8 },
|
||||
end: { offset: 12, line: 1, column: 13 },
|
||||
source: '&'
|
||||
}
|
||||
source: '&',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -109,8 +109,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 14, line: 1, column: 15 },
|
||||
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([
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: ` \na `
|
||||
content: ` \na `,
|
||||
},
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
children: [
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `foo \n bar`
|
||||
}
|
||||
]
|
||||
content: `foo \n bar`,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: ` \n c`
|
||||
}
|
||||
content: ` \n c`,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
|
@ -145,7 +145,7 @@ describe('DOM parser', () => {
|
|||
expect((ast.children[0] as ElementNode).children).toMatchObject([
|
||||
{
|
||||
type: NodeTypes.TEXT,
|
||||
content: `hello`
|
||||
content: `hello`,
|
||||
},
|
||||
{
|
||||
type: NodeTypes.ELEMENT,
|
||||
|
@ -153,10 +153,10 @@ describe('DOM parser', () => {
|
|||
{
|
||||
type: NodeTypes.TEXT,
|
||||
// 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)
|
||||
expect(ast.children[0]).toMatchObject({
|
||||
type: NodeTypes.TEXT,
|
||||
content: `foo${nbsp}${nbsp}bar`
|
||||
content: `foo${nbsp}${nbsp}bar`,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -181,8 +181,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 0, line: 1, column: 1 },
|
||||
end: { offset: 11, line: 1, column: 12 },
|
||||
source: '&ersand;'
|
||||
}
|
||||
source: '&ersand;',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -190,7 +190,7 @@ describe('DOM parser', () => {
|
|||
test('HTML entities compatibility in attribute', () => {
|
||||
const ast = parse(
|
||||
'<div a="&ersand;" b="&ersand;" c="&!"></div>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const element = ast.children[0] as ElementNode
|
||||
const text1 = (element.props[0] as AttributeNode).value
|
||||
|
@ -203,8 +203,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 7, line: 1, column: 8 },
|
||||
end: { offset: 20, line: 1, column: 21 },
|
||||
source: '"&ersand;"'
|
||||
}
|
||||
source: '"&ersand;"',
|
||||
},
|
||||
})
|
||||
expect(text2).toStrictEqual({
|
||||
type: NodeTypes.TEXT,
|
||||
|
@ -212,8 +212,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 23, line: 1, column: 24 },
|
||||
end: { offset: 37, line: 1, column: 38 },
|
||||
source: '"&ersand;"'
|
||||
}
|
||||
source: '"&ersand;"',
|
||||
},
|
||||
})
|
||||
expect(text3).toStrictEqual({
|
||||
type: NodeTypes.TEXT,
|
||||
|
@ -221,8 +221,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 40, line: 1, column: 41 },
|
||||
end: { offset: 47, line: 1, column: 48 },
|
||||
source: '"&!"'
|
||||
}
|
||||
source: '"&!"',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -236,8 +236,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 0, line: 1, column: 1 },
|
||||
end: { offset: 6, line: 1, column: 7 },
|
||||
source: '†'
|
||||
}
|
||||
source: '†',
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -258,14 +258,14 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 8, line: 1, column: 9 },
|
||||
end: { offset: 16, line: 1, column: 17 },
|
||||
source: 'a < b'
|
||||
}
|
||||
source: 'a < b',
|
||||
},
|
||||
},
|
||||
loc: {
|
||||
start: { offset: 5, line: 1, column: 6 },
|
||||
end: { offset: 19, line: 1, column: 20 },
|
||||
source: '{{ a < b }}'
|
||||
}
|
||||
source: '{{ a < b }}',
|
||||
},
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -285,9 +285,9 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 0, line: 1, column: 1 },
|
||||
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({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'div',
|
||||
tagType: ElementTypes.ELEMENT
|
||||
tagType: ElementTypes.ELEMENT,
|
||||
})
|
||||
|
||||
expect(ast.children[1]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'comp',
|
||||
tagType: ElementTypes.COMPONENT
|
||||
tagType: ElementTypes.COMPONENT,
|
||||
})
|
||||
|
||||
expect(ast.children[2]).toMatchObject({
|
||||
type: NodeTypes.ELEMENT,
|
||||
tag: 'Comp',
|
||||
tagType: ElementTypes.COMPONENT
|
||||
tagType: ElementTypes.COMPONENT,
|
||||
})
|
||||
})
|
||||
|
||||
test('Strict end tag detection for textarea.', () => {
|
||||
const ast = parse(
|
||||
'<textarea>hello</textarea</textarea0></texTArea>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const element = ast.children[0] as ElementNode
|
||||
const text = element.children[0] as TextNode
|
||||
|
@ -328,8 +328,8 @@ describe('DOM parser', () => {
|
|||
loc: {
|
||||
start: { offset: 10, line: 1, column: 11 },
|
||||
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', () => {
|
||||
const ast = parse(
|
||||
'<math><annotation-xml><svg></svg></annotation-xml></math>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const elementMath = ast.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', () => {
|
||||
const ast = parse(
|
||||
'<math><annotation-xml encoding="text/html"><test/></annotation-xml></math>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
|
||||
const elementMath = ast.children[0] as ElementNode
|
||||
|
@ -386,7 +386,7 @@ describe('DOM parser', () => {
|
|||
test('html application/xhtml+xml in MATH_ML namespace', () => {
|
||||
const ast = parse(
|
||||
'<math><annotation-xml encoding="application/xhtml+xml"><test/></annotation-xml></math>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const elementMath = ast.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', () => {
|
||||
const ast = parse(
|
||||
'<math><mtext><malignmark/></mtext></math>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const elementMath = ast.children[0] as ElementNode
|
||||
const elementText = elementMath.children[0] as ElementNode
|
||||
|
@ -422,7 +422,7 @@ describe('DOM parser', () => {
|
|||
test('foreignObject tag in SVG namespace', () => {
|
||||
const ast = parse(
|
||||
'<svg><foreignObject><test/></foreignObject></svg>',
|
||||
parserOptions
|
||||
parserOptions,
|
||||
)
|
||||
const elementSvg = ast.children[0] as ElementNode
|
||||
const elementForeignObject = elementSvg.children[0] as ElementNode
|
||||
|
@ -473,7 +473,7 @@ describe('DOM parser', () => {
|
|||
test('root ns', () => {
|
||||
const ast = parse('<foreignObject><test/></foreignObject>', {
|
||||
...parserOptions,
|
||||
ns: Namespaces.SVG
|
||||
ns: Namespaces.SVG,
|
||||
})
|
||||
const elementForieng = ast.children[0] as ElementNode
|
||||
const element = elementForieng.children[0] as ElementNode
|
||||
|
@ -487,13 +487,13 @@ describe('DOM parser', () => {
|
|||
// treatment for <script>, <style>, <textarea> etc.
|
||||
const ast = parse('<script><g/><g/></script>', {
|
||||
...parserOptions,
|
||||
ns: Namespaces.SVG
|
||||
ns: Namespaces.SVG,
|
||||
})
|
||||
const elementSvg = ast.children[0] as ElementNode
|
||||
// should parse as nodes instead of text
|
||||
expect(elementSvg.children).toMatchObject([
|
||||
{ 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(
|
||||
template: string,
|
||||
shouldWarn: boolean,
|
||||
message = `<Transition> expects exactly one child element or component.`
|
||||
message = `<Transition> expects exactly one child element or component.`,
|
||||
) {
|
||||
const spy = vi.fn()
|
||||
compile(template.trim(), {
|
||||
|
@ -12,7 +12,7 @@ describe('Transition multi children warnings', () => {
|
|||
transformHoist: null,
|
||||
onError: err => {
|
||||
spy(err.message)
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
if (shouldWarn) expect(spy).toHaveBeenCalledWith(message)
|
||||
|
@ -27,7 +27,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div>hey</div>
|
||||
</transition>
|
||||
`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -38,7 +38,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div v-for="i in items">hey</div>
|
||||
</transition>
|
||||
`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -50,7 +50,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div v-else v-for="i in items">hey</div>
|
||||
</transition>
|
||||
`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -61,7 +61,7 @@ describe('Transition multi children warnings', () => {
|
|||
<template v-if="ok"></template>
|
||||
</transition>
|
||||
`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -73,7 +73,7 @@ describe('Transition multi children warnings', () => {
|
|||
<template v-else></template>
|
||||
</transition>
|
||||
`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -85,7 +85,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div v-if="other">hey</div>
|
||||
</transition>
|
||||
`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -96,7 +96,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div>hey</div>
|
||||
</transition>
|
||||
`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -107,7 +107,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div v-if="a">hey</div>
|
||||
</transition>
|
||||
`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -120,7 +120,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div v-else>hey</div>
|
||||
</transition>
|
||||
`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -132,7 +132,7 @@ describe('Transition multi children warnings', () => {
|
|||
<div v-else>hey</div>
|
||||
</transition>
|
||||
`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -143,7 +143,7 @@ test('inject persisted when child has v-show', () => {
|
|||
<transition>
|
||||
<div v-show="ok" />
|
||||
</transition>
|
||||
`).code
|
||||
`).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -161,6 +161,6 @@ test('the v-if/else-if/else branches in Transition should ignore comments', () =
|
|||
<p v-else/>
|
||||
</div>
|
||||
</transition>
|
||||
`).code
|
||||
`).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { compile, CompilerError } from '../../src'
|
||||
import { type CompilerError, compile } from '../../src'
|
||||
|
||||
describe('compiler: ignore side effect tags', () => {
|
||||
it('should ignore script', () => {
|
||||
|
@ -6,7 +6,7 @@ describe('compiler: ignore side effect tags', () => {
|
|||
const { code } = compile(`<script>console.log(1)</script>`, {
|
||||
onError(e) {
|
||||
err = e
|
||||
}
|
||||
},
|
||||
})
|
||||
expect(code).not.toMatch('script')
|
||||
expect(err).toBeDefined()
|
||||
|
@ -18,7 +18,7 @@ describe('compiler: ignore side effect tags', () => {
|
|||
const { code } = compile(`<style>h1 { color: red }</style>`, {
|
||||
onError(e) {
|
||||
err = e
|
||||
}
|
||||
},
|
||||
})
|
||||
expect(code).not.toMatch('style')
|
||||
expect(err).toBeDefined()
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import {
|
||||
compile,
|
||||
NodeTypes,
|
||||
CREATE_STATIC,
|
||||
ConstantTypes,
|
||||
NodeTypes,
|
||||
compile,
|
||||
createSimpleExpression,
|
||||
ConstantTypes
|
||||
} from '../../src'
|
||||
import {
|
||||
StringifyThresholds,
|
||||
stringifyStatic,
|
||||
StringifyThresholds
|
||||
} from '../../src/transforms/stringifyStatic'
|
||||
|
||||
describe('stringify static html', () => {
|
||||
|
@ -15,7 +15,7 @@ describe('stringify static html', () => {
|
|||
return compile(template, {
|
||||
hoistStatic: true,
|
||||
prefixIdentifiers: true,
|
||||
transformHoist: stringifyStatic
|
||||
transformHoist: stringifyStatic,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ describe('stringify static html', () => {
|
|||
|
||||
test('should bail on non-eligible static trees', () => {
|
||||
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
|
||||
expect(ast.hoists[0]!.type).toBe(NodeTypes.VNODE_CALL)
|
||||
|
@ -35,8 +35,8 @@ describe('stringify static html', () => {
|
|||
const { ast } = compileWithStringify(
|
||||
`<div><div>${repeat(
|
||||
`<span class="foo"/>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div></div>`,
|
||||
)
|
||||
// should be optimized now
|
||||
expect(ast.hoists).toMatchObject([
|
||||
|
@ -47,15 +47,15 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
`<div>${repeat(
|
||||
`<span class="foo"></span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div>`,
|
||||
),
|
||||
'1'
|
||||
]
|
||||
'1',
|
||||
],
|
||||
}, // 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(
|
||||
`<div><div>${repeat(
|
||||
`<span/>`,
|
||||
StringifyThresholds.NODE_COUNT
|
||||
)}</div></div>`
|
||||
StringifyThresholds.NODE_COUNT,
|
||||
)}</div></div>`,
|
||||
)
|
||||
// should be optimized now
|
||||
expect(ast.hoists).toMatchObject([
|
||||
|
@ -75,16 +75,16 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
`<div>${repeat(
|
||||
`<span></span>`,
|
||||
StringifyThresholds.NODE_COUNT
|
||||
)}</div>`
|
||||
StringifyThresholds.NODE_COUNT,
|
||||
)}</div>`,
|
||||
),
|
||||
'1'
|
||||
]
|
||||
'1',
|
||||
],
|
||||
},
|
||||
// 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(
|
||||
`<div>${repeat(
|
||||
`<span class="foo"/>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div>`,
|
||||
)
|
||||
// should have 6 hoisted nodes (including the entire array),
|
||||
// but 2~5 should be null because they are merged into 1
|
||||
|
@ -105,19 +105,19 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
repeat(
|
||||
`<span class="foo"></span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
),
|
||||
),
|
||||
'5'
|
||||
]
|
||||
'5',
|
||||
],
|
||||
},
|
||||
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(
|
||||
`<div><div :style="{ color: 'red' }">${repeat(
|
||||
`<span :class="[{ foo: true }, { bar: true }]">{{ 1 }} + {{ false }}</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div></div>`,
|
||||
)
|
||||
// should be optimized now
|
||||
expect(ast.hoists).toMatchObject([
|
||||
|
@ -137,15 +137,15 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
`<div style="color:red;">${repeat(
|
||||
`<span class="foo bar">1 + false</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div>`,
|
||||
),
|
||||
'1'
|
||||
]
|
||||
'1',
|
||||
],
|
||||
},
|
||||
{
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION
|
||||
}
|
||||
type: NodeTypes.JS_ARRAY_EXPRESSION,
|
||||
},
|
||||
])
|
||||
})
|
||||
|
||||
|
@ -154,8 +154,8 @@ describe('stringify static html', () => {
|
|||
`<div><div>${repeat(
|
||||
`<span :class="'foo' + '>ar'">{{ 1 }} + {{ '<' }}</span>` +
|
||||
`<span>&</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div></div>`,
|
||||
)
|
||||
// should be optimized now
|
||||
expect(ast.hoists).toMatchObject([
|
||||
|
@ -166,15 +166,15 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
`<div>${repeat(
|
||||
`<span class="foo>ar">1 + <</span>` + `<span>&</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</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(
|
||||
`<div><div>${repeat(
|
||||
`<span class="foo">foo</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}<img src="./foo" /></div></div>`,
|
||||
{
|
||||
hoistStatic: true,
|
||||
|
@ -195,7 +195,7 @@ describe('stringify static html', () => {
|
|||
'_imports_0_',
|
||||
false,
|
||||
node.loc,
|
||||
ConstantTypes.CAN_HOIST
|
||||
ConstantTypes.CAN_HOIST,
|
||||
)
|
||||
node.props[0] = {
|
||||
type: NodeTypes.DIRECTIVE,
|
||||
|
@ -203,23 +203,23 @@ describe('stringify static html', () => {
|
|||
arg: createSimpleExpression('src', true),
|
||||
exp,
|
||||
modifiers: [],
|
||||
loc: node.loc
|
||||
loc: node.loc,
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
expect(ast.hoists).toMatchObject([
|
||||
{
|
||||
// the expression and the tree are still hoistable
|
||||
// but should stay NodeTypes.VNODE_CALL
|
||||
// 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()
|
||||
})
|
||||
|
@ -230,7 +230,7 @@ describe('stringify static html', () => {
|
|||
const { ast, code } = compile(
|
||||
`<div><div>${repeat(
|
||||
`<span class="foo">foo</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}<img src="./foo" /></div></div>`,
|
||||
{
|
||||
hoistStatic: true,
|
||||
|
@ -243,7 +243,7 @@ describe('stringify static html', () => {
|
|||
'_imports_0_',
|
||||
false,
|
||||
node.loc,
|
||||
ConstantTypes.CAN_STRINGIFY
|
||||
ConstantTypes.CAN_STRINGIFY,
|
||||
)
|
||||
node.props[0] = {
|
||||
type: NodeTypes.DIRECTIVE,
|
||||
|
@ -251,22 +251,22 @@ describe('stringify static html', () => {
|
|||
arg: createSimpleExpression('src', true),
|
||||
exp,
|
||||
modifiers: [],
|
||||
loc: node.loc
|
||||
loc: node.loc,
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
expect(ast.hoists).toMatchObject([
|
||||
{
|
||||
// the hoisted node should be NodeTypes.JS_CALL_EXPRESSION
|
||||
// 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()
|
||||
})
|
||||
|
@ -276,31 +276,31 @@ describe('stringify static html', () => {
|
|||
const { ast } = compileWithStringify(
|
||||
`<div><div><input indeterminate>${repeat(
|
||||
`<span class="foo">foo</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div></div>`,
|
||||
)
|
||||
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(
|
||||
`<div><div><input :indeterminate="true">${repeat(
|
||||
`<span class="foo">foo</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div></div>`,
|
||||
)
|
||||
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(
|
||||
`<div><div>${repeat(
|
||||
`<span class="foo">foo</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}<input indeterminate></div></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}<input indeterminate></div></div>`,
|
||||
)
|
||||
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(
|
||||
`<div><div>${repeat(
|
||||
`<span class="foo">foo</span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}<input :indeterminate="true"></div></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}<input :indeterminate="true"></div></div>`,
|
||||
)
|
||||
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(
|
||||
`<table><tbody>${repeat(
|
||||
`<tr class="foo"><td>foo</td></tr>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</tbody></table>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</tbody></table>`,
|
||||
)
|
||||
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(
|
||||
`<foo>${repeat(
|
||||
`<div class="foo"></div>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</foo>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</foo>`,
|
||||
)
|
||||
expect(ast.hoists.length).toBe(
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)
|
||||
ast.hoists.forEach(node => {
|
||||
expect(node).toMatchObject({
|
||||
type: NodeTypes.VNODE_CALL // not CALL_EXPRESSION
|
||||
type: NodeTypes.VNODE_CALL, // not CALL_EXPRESSION
|
||||
})
|
||||
})
|
||||
|
||||
const { ast: ast2 } = compileWithStringify(
|
||||
`<foo><template #foo>${repeat(
|
||||
`<div class="foo"></div>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</template></foo>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</template></foo>`,
|
||||
)
|
||||
expect(ast2.hoists.length).toBe(
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)
|
||||
ast2.hoists.forEach(node => {
|
||||
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(
|
||||
`<div>${repeat(
|
||||
`<span :title="null"></span>`,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</div>`,
|
||||
)
|
||||
expect(ast.hoists[0]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
|
@ -399,11 +399,11 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
`${repeat(
|
||||
`<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(
|
||||
`<button :disabled="false">enable</button>${repeat(
|
||||
`<div></div>`,
|
||||
StringifyThresholds.NODE_COUNT
|
||||
)}`
|
||||
StringifyThresholds.NODE_COUNT,
|
||||
)}`,
|
||||
)
|
||||
expect(ast.hoists[0]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
|
@ -422,11 +422,11 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
`<button>enable</button>${repeat(
|
||||
`<div></div>`,
|
||||
StringifyThresholds.NODE_COUNT
|
||||
)}`
|
||||
StringifyThresholds.NODE_COUNT,
|
||||
)}`,
|
||||
),
|
||||
'21'
|
||||
]
|
||||
'21',
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -436,8 +436,8 @@ describe('stringify static html', () => {
|
|||
const { ast } = compileWithStringify(
|
||||
`<div>${svg}${repeat(
|
||||
repeated,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</svg></div>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</svg></div>`,
|
||||
)
|
||||
expect(ast.hoists[0]).toMatchObject({
|
||||
type: NodeTypes.JS_CALL_EXPRESSION,
|
||||
|
@ -446,11 +446,11 @@ describe('stringify static html', () => {
|
|||
JSON.stringify(
|
||||
`${svg}${repeat(
|
||||
repeated,
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT
|
||||
)}</svg>`
|
||||
StringifyThresholds.ELEMENT_WITH_BINDING_COUNT,
|
||||
)}</svg>`,
|
||||
),
|
||||
'1'
|
||||
]
|
||||
'1',
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {
|
||||
type CompilerOptions,
|
||||
type ElementNode,
|
||||
NodeTypes,
|
||||
type VNodeCall,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
CompilerOptions,
|
||||
ElementNode,
|
||||
NodeTypes,
|
||||
VNodeCall
|
||||
} from '@vue/compiler-core'
|
||||
import { transformBind } from '../../../compiler-core/src/transforms/vBind'
|
||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||
|
@ -12,16 +12,16 @@ import { transformStyle } from '../../src/transforms/transformStyle'
|
|||
|
||||
function transformWithStyleTransform(
|
||||
template: string,
|
||||
options: CompilerOptions = {}
|
||||
options: CompilerOptions = {},
|
||||
) {
|
||||
const ast = parse(template)
|
||||
transform(ast, {
|
||||
nodeTransforms: [transformStyle],
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return {
|
||||
root: ast,
|
||||
node: ast.children[0] as ElementNode
|
||||
node: ast.children[0] as ElementNode,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,13 +34,13 @@ describe('compiler: style transform', () => {
|
|||
arg: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `style`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
exp: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `{"color":"red"}`,
|
||||
isStatic: false
|
||||
}
|
||||
isStatic: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -48,8 +48,8 @@ describe('compiler: style transform', () => {
|
|||
const { node } = transformWithStyleTransform(`<div style="color: red"/>`, {
|
||||
nodeTransforms: [transformStyle, transformElement],
|
||||
directiveTransforms: {
|
||||
bind: transformBind
|
||||
}
|
||||
bind: transformBind,
|
||||
},
|
||||
})
|
||||
expect((node.codegenNode as VNodeCall).props).toMatchObject({
|
||||
type: NodeTypes.JS_OBJECT_EXPRESSION,
|
||||
|
@ -58,15 +58,15 @@ describe('compiler: style transform', () => {
|
|||
key: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `style`,
|
||||
isStatic: true
|
||||
isStatic: true,
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `{"color":"red"}`,
|
||||
isStatic: false
|
||||
}
|
||||
}
|
||||
]
|
||||
isStatic: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
// should not cause the STYLE patchFlag to be attached
|
||||
expect((node.codegenNode as VNodeCall).patchFlag).toBeUndefined()
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
type CompilerOptions,
|
||||
type PlainElementNode,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
PlainElementNode,
|
||||
CompilerOptions
|
||||
} from '@vue/compiler-core'
|
||||
import { transformVHtml } from '../../src/transforms/vHtml'
|
||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||
import {
|
||||
createObjectMatcher,
|
||||
genFlagText
|
||||
genFlagText,
|
||||
} from '../../../compiler-core/__tests__/testUtils'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
import { DOMErrorCodes } from '../../src/errors'
|
||||
|
@ -18,9 +18,9 @@ function transformWithVHtml(template: string, options: CompilerOptions = {}) {
|
|||
transform(ast, {
|
||||
nodeTransforms: [transformElement],
|
||||
directiveTransforms: {
|
||||
html: transformVHtml
|
||||
html: transformVHtml,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -31,40 +31,40 @@ describe('compiler: v-html transform', () => {
|
|||
expect((ast.children[0] as PlainElementNode).codegenNode).toMatchObject({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({
|
||||
innerHTML: `[test]`
|
||||
innerHTML: `[test]`,
|
||||
}),
|
||||
children: undefined,
|
||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||
dynamicProps: `["innerHTML"]`
|
||||
dynamicProps: `["innerHTML"]`,
|
||||
})
|
||||
})
|
||||
|
||||
it('should raise error and ignore children when v-html is present', () => {
|
||||
const onError = vi.fn()
|
||||
const ast = transformWithVHtml(`<div v-html="test">hello</div>`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
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({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({
|
||||
innerHTML: `[test]`
|
||||
innerHTML: `[test]`,
|
||||
}),
|
||||
children: undefined, // <-- children should have been removed
|
||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||
dynamicProps: `["innerHTML"]`
|
||||
dynamicProps: `["innerHTML"]`,
|
||||
})
|
||||
})
|
||||
|
||||
it('should raise error if has no expression', () => {
|
||||
const onError = vi.fn()
|
||||
transformWithVHtml(`<div v-html></div>`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
expect(onError.mock.calls).toMatchObject([
|
||||
[{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }]
|
||||
[{ code: DOMErrorCodes.X_V_HTML_NO_EXPRESSION }],
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
type CompilerOptions,
|
||||
generate,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
CompilerOptions,
|
||||
generate
|
||||
} from '@vue/compiler-core'
|
||||
import { transformModel } from '../../src/transforms/vModel'
|
||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||
|
@ -12,7 +12,7 @@ import {
|
|||
V_MODEL_DYNAMIC,
|
||||
V_MODEL_RADIO,
|
||||
V_MODEL_SELECT,
|
||||
V_MODEL_TEXT
|
||||
V_MODEL_TEXT,
|
||||
} from '../../src/runtimeHelpers'
|
||||
|
||||
function transformWithModel(template: string, options: CompilerOptions = {}) {
|
||||
|
@ -20,9 +20,9 @@ function transformWithModel(template: string, options: CompilerOptions = {}) {
|
|||
transform(ast, {
|
||||
nodeTransforms: [transformElement],
|
||||
directiveTransforms: {
|
||||
model: transformModel
|
||||
model: transformModel,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ describe('compiler: transform v-model', () => {
|
|||
expect(generate(root).code).toMatchSnapshot()
|
||||
|
||||
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(generate(root2).code).toMatchSnapshot()
|
||||
|
@ -98,8 +98,8 @@ describe('compiler: transform v-model', () => {
|
|||
expect(onError).toHaveBeenCalledTimes(1)
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
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).toHaveBeenCalledWith(
|
||||
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 root = transformWithModel('<my-input v-model="model" />', {
|
||||
onError,
|
||||
isCustomElement: tag => tag.startsWith('my-')
|
||||
isCustomElement: tag => tag.startsWith('my-'),
|
||||
})
|
||||
expect(root.helpers).toContain(V_MODEL_TEXT)
|
||||
expect(onError).not.toHaveBeenCalled()
|
||||
|
@ -129,24 +129,24 @@ describe('compiler: transform v-model', () => {
|
|||
test('should raise error if used file input element', () => {
|
||||
const onError = vi.fn()
|
||||
transformWithModel(`<input type="file" v-model="test"/>`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
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', () => {
|
||||
const onError = vi.fn()
|
||||
transformWithModel(`<input v-model="test" :value="test" />`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
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', () => {
|
||||
const onError = vi.fn()
|
||||
transformWithModel(`<input v-model="test" value="test" />`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
expect(onError).not.toHaveBeenCalled()
|
||||
})
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
baseParse as parse,
|
||||
CompilerOptions,
|
||||
ElementNode,
|
||||
TO_HANDLER_KEY,
|
||||
helperNameMap,
|
||||
BindingTypes,
|
||||
type CompilerOptions,
|
||||
type ElementNode,
|
||||
NodeTypes,
|
||||
ObjectExpression,
|
||||
type ObjectExpression,
|
||||
TO_HANDLER_KEY,
|
||||
type VNodeCall,
|
||||
helperNameMap,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
VNodeCall,
|
||||
BindingTypes
|
||||
} from '@vue/compiler-core'
|
||||
import { transformOn } from '../../src/transforms/vOn'
|
||||
import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../../src/runtimeHelpers'
|
||||
|
@ -22,31 +22,31 @@ function parseWithVOn(template: string, options: CompilerOptions = {}) {
|
|||
transform(ast, {
|
||||
nodeTransforms: [transformExpression, transformElement],
|
||||
directiveTransforms: {
|
||||
on: transformOn
|
||||
on: transformOn,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
const node = (ast.children[0] as ElementNode).codegenNode as VNodeCall
|
||||
return {
|
||||
root: ast,
|
||||
node,
|
||||
props: (node.props as ObjectExpression).properties
|
||||
props: (node.props as ObjectExpression).properties,
|
||||
}
|
||||
}
|
||||
|
||||
describe('compiler-dom: transform v-on', () => {
|
||||
it('should support multiple modifiers w/ prefixIdentifiers: true', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @click.stop.prevent="test"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(prop).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
value: {
|
||||
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(
|
||||
`<div @click.stop="test" @keyup.enter="test" />`,
|
||||
{
|
||||
prefixIdentifiers: true
|
||||
}
|
||||
prefixIdentifiers: true,
|
||||
},
|
||||
)
|
||||
const [clickProp, keyUpProp] = props
|
||||
|
||||
|
@ -64,95 +64,95 @@ describe('compiler-dom: transform v-on', () => {
|
|||
type: NodeTypes.JS_PROPERTY,
|
||||
value: {
|
||||
callee: V_ON_WITH_MODIFIERS,
|
||||
arguments: [{ content: '_ctx.test' }, '["stop"]']
|
||||
}
|
||||
arguments: [{ content: '_ctx.test' }, '["stop"]'],
|
||||
},
|
||||
})
|
||||
expect(keyUpProp).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
value: {
|
||||
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', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @click.stop.capture.once="test"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(prop).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
key: {
|
||||
content: `onClickCaptureOnce`
|
||||
content: `onClickCaptureOnce`,
|
||||
},
|
||||
value: {
|
||||
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', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @keydown.stop.capture.ctrl.a="test"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(prop).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
key: {
|
||||
content: `onKeydownCapture`
|
||||
content: `onKeydownCapture`,
|
||||
},
|
||||
value: {
|
||||
callee: V_ON_WITH_KEYS,
|
||||
arguments: [
|
||||
{
|
||||
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', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @keyup.exact="test"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(prop).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
value: {
|
||||
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', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @keyup.left="test"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(prop).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
value: {
|
||||
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', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @[e].left="test"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(prop).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
|
@ -161,41 +161,41 @@ describe('compiler-dom: transform v-on', () => {
|
|||
arguments: [
|
||||
{
|
||||
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', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @keyup.enter="test"/>`, {
|
||||
prefixIdentifiers: true
|
||||
prefixIdentifiers: true,
|
||||
})
|
||||
expect(prop).toMatchObject({
|
||||
type: NodeTypes.JS_PROPERTY,
|
||||
value: {
|
||||
callee: V_ON_WITH_KEYS,
|
||||
arguments: [{ content: '_ctx.test' }, '["enter"]']
|
||||
}
|
||||
arguments: [{ content: '_ctx.test' }, '["enter"]'],
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('should transform click.right', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @click.right="test"/>`)
|
||||
expect(prop.key).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `onContextmenu`
|
||||
content: `onContextmenu`,
|
||||
})
|
||||
|
||||
// dynamic
|
||||
const {
|
||||
props: [prop2]
|
||||
props: [prop2],
|
||||
} = parseWithVOn(`<div @[event].right="test"/>`)
|
||||
// (_toHandlerKey(event)).toLowerCase() === "onclick" ? "onContextmenu" : (_toHandlerKey(event))
|
||||
expect(prop2.key).toMatchObject({
|
||||
|
@ -206,34 +206,34 @@ describe('compiler-dom: transform v-on', () => {
|
|||
children: [
|
||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||
{ content: 'event' },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
`) === "onClick" ? "onContextmenu" : (`,
|
||||
{
|
||||
children: [
|
||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||
{ content: 'event' },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('should transform click.middle', () => {
|
||||
const {
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @click.middle="test"/>`)
|
||||
expect(prop.key).toMatchObject({
|
||||
type: NodeTypes.SIMPLE_EXPRESSION,
|
||||
content: `onMouseup`
|
||||
content: `onMouseup`,
|
||||
})
|
||||
|
||||
// dynamic
|
||||
const {
|
||||
props: [prop2]
|
||||
props: [prop2],
|
||||
} = parseWithVOn(`<div @[event].middle="test"/>`)
|
||||
// (_eventNaming(event)).toLowerCase() === "onclick" ? "onMouseup" : (_eventNaming(event))
|
||||
expect(prop2.key).toMatchObject({
|
||||
|
@ -244,48 +244,48 @@ describe('compiler-dom: transform v-on', () => {
|
|||
children: [
|
||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||
{ content: 'event' },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
`) === "onClick" ? "onMouseup" : (`,
|
||||
{
|
||||
children: [
|
||||
`_${helperNameMap[TO_HANDLER_KEY]}(`,
|
||||
{ content: 'event' },
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
},
|
||||
`)`
|
||||
]
|
||||
`)`,
|
||||
],
|
||||
})
|
||||
})
|
||||
|
||||
test('cache handler w/ modifiers', () => {
|
||||
const {
|
||||
root,
|
||||
props: [prop]
|
||||
props: [prop],
|
||||
} = parseWithVOn(`<div @keyup.enter.capture="foo" />`, {
|
||||
prefixIdentifiers: true,
|
||||
cacheHandlers: true
|
||||
cacheHandlers: true,
|
||||
})
|
||||
expect(root.cached).toBe(1)
|
||||
// should not treat cached handler as dynamicProp, so it should have no
|
||||
// dynamicProps flags and only the hydration flag
|
||||
expect((root as any).children[0].codegenNode.patchFlag).toBe(
|
||||
genFlagText(PatchFlags.NEED_HYDRATION)
|
||||
genFlagText(PatchFlags.NEED_HYDRATION),
|
||||
)
|
||||
expect(prop).toMatchObject({
|
||||
key: {
|
||||
content: `onKeyupCapture`
|
||||
content: `onKeyupCapture`,
|
||||
},
|
||||
value: {
|
||||
type: NodeTypes.JS_CACHE_EXPRESSION,
|
||||
index: 0,
|
||||
value: {
|
||||
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" />`, {
|
||||
prefixIdentifiers: true,
|
||||
bindingMetadata: {
|
||||
foo: BindingTypes.SETUP_CONST
|
||||
foo: BindingTypes.SETUP_CONST,
|
||||
},
|
||||
directiveTransforms: {
|
||||
on: transformOn
|
||||
}
|
||||
on: transformOn,
|
||||
},
|
||||
})
|
||||
// should only have hydration flag
|
||||
expect(node.patchFlag).toBe(genFlagText(PatchFlags.NEED_HYDRATION))
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
type CompilerOptions,
|
||||
generate,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
generate,
|
||||
CompilerOptions
|
||||
} from '@vue/compiler-core'
|
||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||
import { transformShow } from '../../src/transforms/vShow'
|
||||
|
@ -13,9 +13,9 @@ function transformWithShow(template: string, options: CompilerOptions = {}) {
|
|||
transform(ast, {
|
||||
nodeTransforms: [transformElement],
|
||||
directiveTransforms: {
|
||||
show: transformShow
|
||||
show: transformShow,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -34,8 +34,8 @@ describe('compiler: v-show transform', () => {
|
|||
expect(onError).toHaveBeenCalledTimes(1)
|
||||
expect(onError).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
code: DOMErrorCodes.X_V_SHOW_NO_EXPRESSION
|
||||
})
|
||||
code: DOMErrorCodes.X_V_SHOW_NO_EXPRESSION,
|
||||
}),
|
||||
)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
type CompilerOptions,
|
||||
type PlainElementNode,
|
||||
baseParse as parse,
|
||||
transform,
|
||||
PlainElementNode,
|
||||
CompilerOptions
|
||||
} from '@vue/compiler-core'
|
||||
import { transformVText } from '../../src/transforms/vText'
|
||||
import { transformElement } from '../../../compiler-core/src/transforms/transformElement'
|
||||
import {
|
||||
createObjectMatcher,
|
||||
genFlagText
|
||||
genFlagText,
|
||||
} from '../../../compiler-core/__tests__/testUtils'
|
||||
import { PatchFlags } from '@vue/shared'
|
||||
import { DOMErrorCodes } from '../../src/errors'
|
||||
|
@ -18,9 +18,9 @@ function transformWithVText(template: string, options: CompilerOptions = {}) {
|
|||
transform(ast, {
|
||||
nodeTransforms: [transformElement],
|
||||
directiveTransforms: {
|
||||
text: transformVText
|
||||
text: transformVText,
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
return ast
|
||||
}
|
||||
|
@ -32,43 +32,43 @@ describe('compiler: v-text transform', () => {
|
|||
tag: `"div"`,
|
||||
props: createObjectMatcher({
|
||||
textContent: {
|
||||
arguments: [{ content: 'test' }]
|
||||
}
|
||||
arguments: [{ content: 'test' }],
|
||||
},
|
||||
}),
|
||||
children: undefined,
|
||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||
dynamicProps: `["textContent"]`
|
||||
dynamicProps: `["textContent"]`,
|
||||
})
|
||||
})
|
||||
|
||||
it('should raise error and ignore children when v-text is present', () => {
|
||||
const onError = vi.fn()
|
||||
const ast = transformWithVText(`<div v-text="test">hello</div>`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
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({
|
||||
tag: `"div"`,
|
||||
props: createObjectMatcher({
|
||||
textContent: {
|
||||
arguments: [{ content: 'test' }]
|
||||
}
|
||||
arguments: [{ content: 'test' }],
|
||||
},
|
||||
}),
|
||||
children: undefined, // <-- children should have been removed
|
||||
patchFlag: genFlagText(PatchFlags.PROPS),
|
||||
dynamicProps: `["textContent"]`
|
||||
dynamicProps: `["textContent"]`,
|
||||
})
|
||||
})
|
||||
|
||||
it('should raise error if has no expression', () => {
|
||||
const onError = vi.fn()
|
||||
transformWithVText(`<div v-text></div>`, {
|
||||
onError
|
||||
onError,
|
||||
})
|
||||
expect(onError.mock.calls).toMatchObject([
|
||||
[{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }]
|
||||
[{ code: DOMErrorCodes.X_V_TEXT_NO_EXPRESSION }],
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
SourceLocation,
|
||||
CompilerError,
|
||||
type CompilerError,
|
||||
ErrorCodes,
|
||||
type SourceLocation,
|
||||
createCompilerError,
|
||||
ErrorCodes
|
||||
} from '@vue/compiler-core'
|
||||
|
||||
export interface DOMCompilerError extends CompilerError {
|
||||
|
@ -11,12 +11,12 @@ export interface DOMCompilerError extends CompilerError {
|
|||
|
||||
export function createDOMCompilerError(
|
||||
code: DOMErrorCodes,
|
||||
loc?: SourceLocation
|
||||
loc?: SourceLocation,
|
||||
) {
|
||||
return createCompilerError(
|
||||
code,
|
||||
loc,
|
||||
__DEV__ || !__BROWSER__ ? DOMErrorMessages : undefined
|
||||
__DEV__ || !__BROWSER__ ? DOMErrorMessages : undefined,
|
||||
) as DOMCompilerError
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ export enum DOMErrorCodes {
|
|||
X_V_SHOW_NO_EXPRESSION,
|
||||
X_TRANSITION_INVALID_CHILDREN,
|
||||
X_IGNORED_SIDE_EFFECT_TAG,
|
||||
__EXTEND_POINT__
|
||||
__EXTEND_POINT__,
|
||||
}
|
||||
|
||||
if (__TEST__) {
|
||||
|
@ -43,7 +43,7 @@ if (__TEST__) {
|
|||
throw new Error(
|
||||
`DOMErrorCodes need to be updated to ${
|
||||
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_SHOW_NO_EXPRESSION]: `v-show is missing expression.`,
|
||||
[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 {
|
||||
type CodegenResult,
|
||||
type CompilerOptions,
|
||||
type DirectiveTransform,
|
||||
type NodeTransform,
|
||||
type ParserOptions,
|
||||
type RootNode,
|
||||
baseCompile,
|
||||
baseParse,
|
||||
CompilerOptions,
|
||||
CodegenResult,
|
||||
ParserOptions,
|
||||
RootNode,
|
||||
noopDirectiveTransform,
|
||||
NodeTransform,
|
||||
DirectiveTransform
|
||||
} from '@vue/compiler-core'
|
||||
import { parserOptions } from './parserOptions'
|
||||
import { transformStyle } from './transforms/transformStyle'
|
||||
|
@ -25,7 +25,7 @@ export { parserOptions }
|
|||
|
||||
export const DOMNodeTransforms: NodeTransform[] = [
|
||||
transformStyle,
|
||||
...(__DEV__ ? [transformTransition] : [])
|
||||
...(__DEV__ ? [transformTransition] : []),
|
||||
]
|
||||
|
||||
export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
|
||||
|
@ -34,12 +34,12 @@ export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
|
|||
text: transformVText,
|
||||
model: transformModel, // override compiler-core
|
||||
on: transformOn, // override compiler-core
|
||||
show: transformShow
|
||||
show: transformShow,
|
||||
}
|
||||
|
||||
export function compile(
|
||||
src: string | RootNode,
|
||||
options: CompilerOptions = {}
|
||||
options: CompilerOptions = {},
|
||||
): CodegenResult {
|
||||
return baseCompile(
|
||||
src,
|
||||
|
@ -50,15 +50,15 @@ export function compile(
|
|||
// by compiler-ssr to generate vnode fallback branches
|
||||
ignoreSideEffectTags,
|
||||
...DOMNodeTransforms,
|
||||
...(options.nodeTransforms || [])
|
||||
...(options.nodeTransforms || []),
|
||||
],
|
||||
directiveTransforms: extend(
|
||||
{},
|
||||
DOMDirectiveTransforms,
|
||||
options.directiveTransforms || {}
|
||||
options.directiveTransforms || {},
|
||||
),
|
||||
transformHoist: __BROWSER__ ? null : stringifyStatic
|
||||
})
|
||||
transformHoist: __BROWSER__ ? null : stringifyStatic,
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,6 @@ export { transformStyle } from './transforms/transformStyle'
|
|||
export {
|
||||
createDOMCompilerError,
|
||||
DOMErrorCodes,
|
||||
DOMErrorMessages
|
||||
DOMErrorMessages,
|
||||
} from './errors'
|
||||
export * from '@vue/compiler-core'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { ParserOptions, NodeTypes, Namespaces } from '@vue/compiler-core'
|
||||
import { isVoidTag, isHTMLTag, isSVGTag, isMathMLTag } from '@vue/shared'
|
||||
import { Namespaces, NodeTypes, type ParserOptions } from '@vue/compiler-core'
|
||||
import { isHTMLTag, isMathMLTag, isSVGTag, isVoidTag } from '@vue/shared'
|
||||
import { TRANSITION, TRANSITION_GROUP } from './runtimeHelpers'
|
||||
import { decodeHtmlBrowser } from './decodeHtmlBrowser'
|
||||
|
||||
|
@ -33,7 +33,7 @@ export const parserOptions: ParserOptions = {
|
|||
a.name === 'encoding' &&
|
||||
a.value != null &&
|
||||
(a.value.content === 'text/html' ||
|
||||
a.value.content === 'application/xhtml+xml')
|
||||
a.value.content === 'application/xhtml+xml'),
|
||||
)
|
||||
) {
|
||||
ns = Namespaces.HTML
|
||||
|
@ -64,5 +64,5 @@ export const parserOptions: ParserOptions = {
|
|||
}
|
||||
}
|
||||
return ns
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
@ -24,5 +24,5 @@ registerRuntimeHelpers({
|
|||
[V_ON_WITH_KEYS]: `withKeys`,
|
||||
[V_SHOW]: `vShow`,
|
||||
[TRANSITION]: `Transition`,
|
||||
[TRANSITION_GROUP]: `TransitionGroup`
|
||||
[TRANSITION_GROUP]: `TransitionGroup`,
|
||||
})
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import {
|
||||
NodeTransform,
|
||||
NodeTypes,
|
||||
type ComponentNode,
|
||||
ElementTypes,
|
||||
ComponentNode,
|
||||
IfBranchNode
|
||||
type IfBranchNode,
|
||||
type NodeTransform,
|
||||
NodeTypes,
|
||||
} from '@vue/compiler-core'
|
||||
import { TRANSITION } from '../runtimeHelpers'
|
||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||
|
||||
export const transformTransition: NodeTransform = (node, context) => {
|
||||
if (
|
||||
|
@ -28,9 +28,9 @@ export const transformTransition: NodeTransform = (node, context) => {
|
|||
{
|
||||
start: node.children[0].loc.start,
|
||||
end: node.children[node.children.length - 1].loc.end,
|
||||
source: ''
|
||||
}
|
||||
)
|
||||
source: '',
|
||||
},
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,7 @@ export const transformTransition: NodeTransform = (node, context) => {
|
|||
name: 'persisted',
|
||||
nameLoc: node.loc,
|
||||
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(
|
||||
c =>
|
||||
c.type !== NodeTypes.COMMENT &&
|
||||
!(c.type === NodeTypes.TEXT && !c.content.trim())
|
||||
!(c.type === NodeTypes.TEXT && !c.content.trim()),
|
||||
))
|
||||
const child = children[0]
|
||||
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'
|
||||
|
||||
export const ignoreSideEffectTags: NodeTransform = (node, context) => {
|
||||
|
@ -11,8 +11,8 @@ export const ignoreSideEffectTags: NodeTransform = (node, context) => {
|
|||
context.onError(
|
||||
createDOMCompilerError(
|
||||
DOMErrorCodes.X_IGNORED_SIDE_EFFECT_TAG,
|
||||
node.loc
|
||||
)
|
||||
node.loc,
|
||||
),
|
||||
)
|
||||
context.removeNode()
|
||||
}
|
||||
|
|
|
@ -2,40 +2,40 @@
|
|||
* This module is Node-only.
|
||||
*/
|
||||
import {
|
||||
NodeTypes,
|
||||
ElementNode,
|
||||
TransformContext,
|
||||
TemplateChildNode,
|
||||
SimpleExpressionNode,
|
||||
createCallExpression,
|
||||
HoistTransform,
|
||||
CREATE_STATIC,
|
||||
ExpressionNode,
|
||||
ElementTypes,
|
||||
PlainElementNode,
|
||||
JSChildNode,
|
||||
TextCallNode,
|
||||
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'
|
||||
import {
|
||||
isVoidTag,
|
||||
escapeHtml,
|
||||
isBooleanAttr,
|
||||
isKnownHtmlAttr,
|
||||
isKnownSvgAttr,
|
||||
isString,
|
||||
isSymbol,
|
||||
isKnownHtmlAttr,
|
||||
escapeHtml,
|
||||
toDisplayString,
|
||||
isVoidTag,
|
||||
makeMap,
|
||||
normalizeClass,
|
||||
normalizeStyle,
|
||||
stringifyStyle,
|
||||
makeMap,
|
||||
isKnownSvgAttr,
|
||||
isBooleanAttr
|
||||
toDisplayString,
|
||||
} from '@vue/shared'
|
||||
|
||||
export enum StringifyThresholds {
|
||||
ELEMENT_WITH_BINDING_COUNT = 5,
|
||||
NODE_COUNT = 20
|
||||
NODE_COUNT = 20,
|
||||
}
|
||||
|
||||
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
|
||||
const staticCall = createCallExpression(context.helper(CREATE_STATIC), [
|
||||
JSON.stringify(
|
||||
currentChunk.map(node => stringifyNode(node, context)).join('')
|
||||
currentChunk.map(node => stringifyNode(node, context)).join(''),
|
||||
).replace(expReplaceRE, `" + $1 + "`),
|
||||
// the 2nd argument indicates the number of DOM nodes this static vnode
|
||||
// will insert / hydrate
|
||||
String(currentChunk.length)
|
||||
String(currentChunk.length),
|
||||
])
|
||||
// replace the first node's hoisted expression with the static vnode call
|
||||
replaceHoist(currentChunk[0], staticCall, context)
|
||||
|
@ -161,14 +161,14 @@ const isStringifiableAttr = (name: string, ns: Namespaces) => {
|
|||
const replaceHoist = (
|
||||
node: StringifiableNode,
|
||||
replacement: JSChildNode | null,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
) => {
|
||||
const hoistToReplace = (node.codegenNode as SimpleExpressionNode).hoisted!
|
||||
context.hoists[context.hoists.indexOf(hoistToReplace)] = replacement
|
||||
}
|
||||
|
||||
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(
|
||||
node: string | TemplateChildNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): string {
|
||||
if (isString(node)) {
|
||||
return node
|
||||
|
@ -277,7 +277,7 @@ function stringifyNode(
|
|||
|
||||
function stringifyElement(
|
||||
node: ElementNode,
|
||||
context: TransformContext
|
||||
context: TransformContext,
|
||||
): string {
|
||||
let res = `<${node.tag}`
|
||||
let innerHTML = ''
|
||||
|
@ -316,7 +316,7 @@ function stringifyElement(
|
|||
evaluated = stringifyStyle(normalizeStyle(evaluated))
|
||||
}
|
||||
res += ` ${(p.arg as SimpleExpressionNode).content}="${escapeHtml(
|
||||
evaluated
|
||||
evaluated,
|
||||
)}"`
|
||||
}
|
||||
} else if (p.name === 'html') {
|
||||
|
@ -325,7 +325,7 @@ function stringifyElement(
|
|||
innerHTML = evaluateConstant(p.exp as SimpleExpressionNode)
|
||||
} else if (p.name === 'text') {
|
||||
innerHTML = escapeHtml(
|
||||
toDisplayString(evaluateConstant(p.exp as SimpleExpressionNode))
|
||||
toDisplayString(evaluateConstant(p.exp as SimpleExpressionNode)),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {
|
||||
NodeTransform,
|
||||
ConstantTypes,
|
||||
type NodeTransform,
|
||||
NodeTypes,
|
||||
type SimpleExpressionNode,
|
||||
type SourceLocation,
|
||||
createSimpleExpression,
|
||||
SimpleExpressionNode,
|
||||
SourceLocation,
|
||||
ConstantTypes
|
||||
} from '@vue/compiler-core'
|
||||
import { parseStringStyle } from '@vue/shared'
|
||||
|
||||
|
@ -25,7 +25,7 @@ export const transformStyle: NodeTransform = node => {
|
|||
arg: createSimpleExpression(`style`, true, p.loc),
|
||||
exp: parseInlineCSS(p.value.content, p.loc),
|
||||
modifiers: [],
|
||||
loc: p.loc
|
||||
loc: p.loc,
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -34,13 +34,13 @@ export const transformStyle: NodeTransform = node => {
|
|||
|
||||
const parseInlineCSS = (
|
||||
cssText: string,
|
||||
loc: SourceLocation
|
||||
loc: SourceLocation,
|
||||
): SimpleExpressionNode => {
|
||||
const normalized = parseStringStyle(cssText)
|
||||
return createSimpleExpression(
|
||||
JSON.stringify(normalized),
|
||||
false,
|
||||
loc,
|
||||
ConstantTypes.CAN_STRINGIFY
|
||||
ConstantTypes.CAN_STRINGIFY,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import {
|
||||
DirectiveTransform,
|
||||
type DirectiveTransform,
|
||||
createObjectProperty,
|
||||
createSimpleExpression
|
||||
createSimpleExpression,
|
||||
} from '@vue/compiler-core'
|
||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||
|
||||
export const transformVHtml: DirectiveTransform = (dir, node, context) => {
|
||||
const { exp, loc } = dir
|
||||
if (!exp) {
|
||||
context.onError(
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc)
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_HTML_NO_EXPRESSION, loc),
|
||||
)
|
||||
}
|
||||
if (node.children.length) {
|
||||
context.onError(
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc)
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_HTML_WITH_CHILDREN, loc),
|
||||
)
|
||||
node.children.length = 0
|
||||
}
|
||||
|
@ -22,8 +22,8 @@ export const transformVHtml: DirectiveTransform = (dir, node, context) => {
|
|||
props: [
|
||||
createObjectProperty(
|
||||
createSimpleExpression(`innerHTML`, true, loc),
|
||||
exp || createSimpleExpression('', true)
|
||||
)
|
||||
]
|
||||
exp || createSimpleExpression('', true),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import {
|
||||
transformModel as baseTransform,
|
||||
DirectiveTransform,
|
||||
type DirectiveTransform,
|
||||
ElementTypes,
|
||||
findProp,
|
||||
NodeTypes,
|
||||
hasDynamicKeyVBind,
|
||||
transformModel as baseTransform,
|
||||
findDir,
|
||||
isStaticArgOf
|
||||
findProp,
|
||||
hasDynamicKeyVBind,
|
||||
isStaticArgOf,
|
||||
} from '@vue/compiler-core'
|
||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||
import {
|
||||
V_MODEL_CHECKBOX,
|
||||
V_MODEL_DYNAMIC,
|
||||
V_MODEL_RADIO,
|
||||
V_MODEL_SELECT,
|
||||
V_MODEL_TEXT,
|
||||
V_MODEL_DYNAMIC
|
||||
} from '../runtimeHelpers'
|
||||
|
||||
export const transformModel: DirectiveTransform = (dir, node, context) => {
|
||||
|
@ -28,8 +28,8 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
context.onError(
|
||||
createDOMCompilerError(
|
||||
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(
|
||||
createDOMCompilerError(
|
||||
DOMErrorCodes.X_V_MODEL_UNNECESSARY_VALUE,
|
||||
value.loc
|
||||
)
|
||||
value.loc,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -74,8 +74,8 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
context.onError(
|
||||
createDOMCompilerError(
|
||||
DOMErrorCodes.X_V_MODEL_ON_FILE_INPUT_ELEMENT,
|
||||
dir.loc
|
||||
)
|
||||
dir.loc,
|
||||
),
|
||||
)
|
||||
break
|
||||
default:
|
||||
|
@ -108,8 +108,8 @@ export const transformModel: DirectiveTransform = (dir, node, context) => {
|
|||
context.onError(
|
||||
createDOMCompilerError(
|
||||
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.content === 'modelValue'
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
return baseResult
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
import {
|
||||
transformOn as baseTransform,
|
||||
DirectiveTransform,
|
||||
createObjectProperty,
|
||||
createCallExpression,
|
||||
createSimpleExpression,
|
||||
NodeTypes,
|
||||
createCompoundExpression,
|
||||
ExpressionNode,
|
||||
SimpleExpressionNode,
|
||||
isStaticExp,
|
||||
CompilerDeprecationTypes,
|
||||
TransformContext,
|
||||
SourceLocation,
|
||||
checkCompatEnabled
|
||||
type DirectiveTransform,
|
||||
type ExpressionNode,
|
||||
NodeTypes,
|
||||
type SimpleExpressionNode,
|
||||
type SourceLocation,
|
||||
type TransformContext,
|
||||
transformOn as baseTransform,
|
||||
checkCompatEnabled,
|
||||
createCallExpression,
|
||||
createCompoundExpression,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
isStaticExp,
|
||||
} from '@vue/compiler-core'
|
||||
import { V_ON_WITH_MODIFIERS, V_ON_WITH_KEYS } from '../runtimeHelpers'
|
||||
import { makeMap, capitalize } from '@vue/shared'
|
||||
import { V_ON_WITH_KEYS, V_ON_WITH_MODIFIERS } from '../runtimeHelpers'
|
||||
import { capitalize, makeMap } from '@vue/shared'
|
||||
|
||||
const isEventOptionModifier = /*#__PURE__*/ makeMap(`passive,once,capture`)
|
||||
const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
||||
|
@ -24,20 +24,20 @@ const isNonKeyModifier = /*#__PURE__*/ makeMap(
|
|||
// system modifiers + exact
|
||||
`ctrl,shift,alt,meta,exact,` +
|
||||
// mouse
|
||||
`middle`
|
||||
`middle`,
|
||||
)
|
||||
// left & right could be mouse or key modifiers based on event type
|
||||
const maybeKeyModifier = /*#__PURE__*/ makeMap('left,right')
|
||||
const isKeyboardEvent = /*#__PURE__*/ makeMap(
|
||||
`onkeyup,onkeydown,onkeypress`,
|
||||
true
|
||||
true,
|
||||
)
|
||||
|
||||
const resolveModifiers = (
|
||||
key: ExpressionNode,
|
||||
modifiers: string[],
|
||||
context: TransformContext,
|
||||
loc: SourceLocation
|
||||
loc: SourceLocation,
|
||||
) => {
|
||||
const keyModifiers = []
|
||||
const nonKeyModifiers = []
|
||||
|
@ -52,7 +52,7 @@ const resolveModifiers = (
|
|||
checkCompatEnabled(
|
||||
CompilerDeprecationTypes.COMPILER_V_ON_NATIVE,
|
||||
context,
|
||||
loc
|
||||
loc,
|
||||
)
|
||||
) {
|
||||
eventOptionModifiers.push(modifier)
|
||||
|
@ -86,7 +86,7 @@ const resolveModifiers = (
|
|||
return {
|
||||
keyModifiers,
|
||||
nonKeyModifiers,
|
||||
eventOptionModifiers
|
||||
eventOptionModifiers,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ const transformClick = (key: ExpressionNode, event: string) => {
|
|||
key,
|
||||
`) === "onClick" ? "${event}" : (`,
|
||||
key,
|
||||
`)`
|
||||
`)`,
|
||||
])
|
||||
: key
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
|
|||
if (nonKeyModifiers.length) {
|
||||
handlerExp = createCallExpression(context.helper(V_ON_WITH_MODIFIERS), [
|
||||
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,
|
||||
JSON.stringify(keyModifiers)
|
||||
JSON.stringify(keyModifiers),
|
||||
])
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ export const transformOn: DirectiveTransform = (dir, node, context) => {
|
|||
}
|
||||
|
||||
return {
|
||||
props: [createObjectProperty(key, handlerExp)]
|
||||
props: [createObjectProperty(key, handlerExp)],
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import { DirectiveTransform } from '@vue/compiler-core'
|
||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||
import type { DirectiveTransform } from '@vue/compiler-core'
|
||||
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||
import { V_SHOW } from '../runtimeHelpers'
|
||||
|
||||
export const transformShow: DirectiveTransform = (dir, node, context) => {
|
||||
const { exp, loc } = dir
|
||||
if (!exp) {
|
||||
context.onError(
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc)
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_SHOW_NO_EXPRESSION, loc),
|
||||
)
|
||||
}
|
||||
|
||||
return {
|
||||
props: [],
|
||||
needRuntime: context.helper(V_SHOW)
|
||||
needRuntime: context.helper(V_SHOW),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +1,23 @@
|
|||
import {
|
||||
DirectiveTransform,
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
type DirectiveTransform,
|
||||
TO_DISPLAY_STRING,
|
||||
createCallExpression,
|
||||
getConstantType
|
||||
createObjectProperty,
|
||||
createSimpleExpression,
|
||||
getConstantType,
|
||||
} from '@vue/compiler-core'
|
||||
import { createDOMCompilerError, DOMErrorCodes } from '../errors'
|
||||
import { DOMErrorCodes, createDOMCompilerError } from '../errors'
|
||||
|
||||
export const transformVText: DirectiveTransform = (dir, node, context) => {
|
||||
const { exp, loc } = dir
|
||||
if (!exp) {
|
||||
context.onError(
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc)
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_NO_EXPRESSION, loc),
|
||||
)
|
||||
}
|
||||
if (node.children.length) {
|
||||
context.onError(
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc)
|
||||
createDOMCompilerError(DOMErrorCodes.X_V_TEXT_WITH_CHILDREN, loc),
|
||||
)
|
||||
node.children.length = 0
|
||||
}
|
||||
|
@ -31,10 +31,10 @@ export const transformVText: DirectiveTransform = (dir, node, context) => {
|
|||
: createCallExpression(
|
||||
context.helperString(TO_DISPLAY_STRING),
|
||||
[exp],
|
||||
loc
|
||||
loc,
|
||||
)
|
||||
: createSimpleExpression('', true)
|
||||
)
|
||||
]
|
||||
: createSimpleExpression('', true),
|
||||
),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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>', () => {
|
||||
test('should compile JS syntax', () => {
|
||||
|
@ -34,7 +34,7 @@ describe('SFC compile <script setup>', () => {
|
|||
expect(content).toMatch(
|
||||
`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, ` +
|
||||
`get xx() { return xx }, get x() { return x } }`
|
||||
`get xx() { return xx }, get x() { return x } }`,
|
||||
)
|
||||
expect(bindings).toStrictEqual({
|
||||
x: BindingTypes.SETUP_MAYBE_REF,
|
||||
|
@ -46,7 +46,7 @@ describe('SFC compile <script setup>', () => {
|
|||
aa: BindingTypes.SETUP_LET,
|
||||
bb: BindingTypes.LITERAL_CONST,
|
||||
cc: BindingTypes.SETUP_CONST,
|
||||
dd: BindingTypes.SETUP_CONST
|
||||
dd: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -63,7 +63,7 @@ describe('SFC compile <script setup>', () => {
|
|||
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||
baz: BindingTypes.SETUP_MAYBE_REF,
|
||||
y: BindingTypes.SETUP_MAYBE_REF,
|
||||
z: BindingTypes.SETUP_MAYBE_REF
|
||||
z: BindingTypes.SETUP_MAYBE_REF,
|
||||
})
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -209,7 +209,7 @@ describe('SFC compile <script setup>', () => {
|
|||
compile(`<script setup>
|
||||
import { ref } from 'vue'
|
||||
import 'foo/css'
|
||||
</script>`).content
|
||||
</script>`).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -220,7 +220,7 @@ describe('SFC compile <script setup>', () => {
|
|||
import a from 'a' // comment
|
||||
import b from 'b'
|
||||
</script>
|
||||
`).content
|
||||
`).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -232,7 +232,7 @@ describe('SFC compile <script setup>', () => {
|
|||
defineProps(['foo'])
|
||||
defineEmits(['bar'])
|
||||
const r = ref(0)
|
||||
</script>`).content
|
||||
</script>`).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -249,11 +249,11 @@ describe('SFC compile <script setup>', () => {
|
|||
color: v-bind(msg)
|
||||
}
|
||||
</style>
|
||||
`
|
||||
`,
|
||||
)
|
||||
assertCode(content)
|
||||
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'`)
|
||||
})
|
||||
|
@ -270,7 +270,7 @@ describe('SFC compile <script setup>', () => {
|
|||
`)
|
||||
assertCode(content)
|
||||
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,
|
||||
reactive: 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,
|
||||
_ref: 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({
|
||||
bar: BindingTypes.SETUP_REACTIVE_CONST,
|
||||
x: BindingTypes.SETUP_CONST
|
||||
x: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -334,7 +334,7 @@ describe('SFC compile <script setup>', () => {
|
|||
`)
|
||||
assertCode(content)
|
||||
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
|
||||
expect(content).toMatch(
|
||||
`return { fooBar, get FooBaz() { return FooBaz }, ` +
|
||||
`get FooQux() { return FooQux }, get foo() { return foo } }`
|
||||
`get FooQux() { return FooQux }, get foo() { return foo } }`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -396,7 +396,7 @@ describe('SFC compile <script setup>', () => {
|
|||
`)
|
||||
expect(content).toMatch(
|
||||
`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)
|
||||
})
|
||||
|
@ -413,7 +413,7 @@ describe('SFC compile <script setup>', () => {
|
|||
</template>
|
||||
`)
|
||||
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)
|
||||
})
|
||||
|
@ -431,7 +431,7 @@ describe('SFC compile <script setup>', () => {
|
|||
// y: should not be matched by {{ yy }} or 'y' in binding exps
|
||||
// x$y: #4274 should escape special chars when creating Regex
|
||||
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)
|
||||
})
|
||||
|
@ -448,7 +448,7 @@ describe('SFC compile <script setup>', () => {
|
|||
`)
|
||||
// VAR2 should not be matched
|
||||
expect(content).toMatch(
|
||||
`return { get VAR() { return VAR }, get VAR3() { return VAR3 } }`
|
||||
`return { get VAR() { return VAR }, get VAR3() { return VAR3 } }`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -465,7 +465,7 @@ describe('SFC compile <script setup>', () => {
|
|||
</template>
|
||||
`)
|
||||
expect(content).toMatch(
|
||||
`return { get FooBaz() { return FooBaz }, get Last() { return Last } }`
|
||||
`return { get FooBaz() { return FooBaz }, get Last() { return Last } }`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -514,7 +514,7 @@ describe('SFC compile <script setup>', () => {
|
|||
</template>
|
||||
`)
|
||||
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)
|
||||
})
|
||||
|
@ -573,7 +573,7 @@ describe('SFC compile <script setup>', () => {
|
|||
<div>static</div>
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
// check snapshot and make sure helper imports and
|
||||
// hoists are placed correctly.
|
||||
|
@ -591,7 +591,7 @@ describe('SFC compile <script setup>', () => {
|
|||
defineExpose({ count })
|
||||
</script>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`setup(__props, { expose: __expose })`)
|
||||
|
@ -612,7 +612,7 @@ describe('SFC compile <script setup>', () => {
|
|||
<some-other-comp/>
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
expect(content).toMatch('[_unref(vMyDir)]')
|
||||
expect(content).toMatch('_createVNode(ChildComp)')
|
||||
|
@ -641,7 +641,7 @@ describe('SFC compile <script setup>', () => {
|
|||
{{ tree.foo() }}
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
// no need to unref vue component import
|
||||
expect(content).toMatch(`createVNode(Foo,`)
|
||||
|
@ -680,7 +680,7 @@ describe('SFC compile <script setup>', () => {
|
|||
<input v-model="lett">
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
// known const ref: set value
|
||||
expect(content).toMatch(`(count).value = $event`)
|
||||
|
@ -688,7 +688,7 @@ describe('SFC compile <script setup>', () => {
|
|||
expect(content).toMatch(`_isRef(maybe) ? (maybe).value = $event : null`)
|
||||
// let: handle both cases
|
||||
expect(content).toMatch(
|
||||
`_isRef(lett) ? (lett).value = $event : lett = $event`
|
||||
`_isRef(lett) ? (lett).value = $event : lett = $event`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -708,7 +708,7 @@ describe('SFC compile <script setup>', () => {
|
|||
<input v-model="foo">
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
expect(content).not.toMatch(`_isRef(foo)`)
|
||||
})
|
||||
|
@ -746,7 +746,7 @@ describe('SFC compile <script setup>', () => {
|
|||
}"/>
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
// known const ref: set value
|
||||
expect(content).toMatch(`count.value = 1`)
|
||||
|
@ -754,7 +754,7 @@ describe('SFC compile <script setup>', () => {
|
|||
expect(content).toMatch(`maybe.value = count.value`)
|
||||
// let: handle both cases
|
||||
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`)
|
||||
|
@ -780,7 +780,7 @@ describe('SFC compile <script setup>', () => {
|
|||
<div @click="--lett"/>
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
// known const ref: set value
|
||||
expect(content).toMatch(`count.value++`)
|
||||
|
@ -809,7 +809,7 @@ describe('SFC compile <script setup>', () => {
|
|||
<div @click="({ lett } = val)"/>
|
||||
</template>
|
||||
`,
|
||||
{ inlineTemplate: true }
|
||||
{ inlineTemplate: true },
|
||||
)
|
||||
// known const ref: set value
|
||||
expect(content).toMatch(`({ count: count.value } = val)`)
|
||||
|
@ -840,9 +840,9 @@ describe('SFC compile <script setup>', () => {
|
|||
{
|
||||
inlineTemplate: true,
|
||||
templateOptions: {
|
||||
ssr: true
|
||||
}
|
||||
}
|
||||
ssr: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
expect(content).toMatch(`\n __ssrInlineRender: true,\n`)
|
||||
expect(content).toMatch(`return (_ctx, _push`)
|
||||
|
@ -866,9 +866,9 @@ describe('SFC compile <script setup>', () => {
|
|||
</template>
|
||||
`,
|
||||
{
|
||||
inlineTemplate: false
|
||||
}
|
||||
)
|
||||
inlineTemplate: false,
|
||||
},
|
||||
),
|
||||
).not.toThrowError()
|
||||
})
|
||||
})
|
||||
|
@ -887,11 +887,11 @@ describe('SFC compile <script setup>', () => {
|
|||
const { content, bindings } = compile(
|
||||
`<script setup lang="ts">
|
||||
enum Foo { A = 123 }
|
||||
</script>`
|
||||
</script>`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
Foo: BindingTypes.LITERAL_CONST
|
||||
Foo: BindingTypes.LITERAL_CONST,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -904,14 +904,14 @@ describe('SFC compile <script setup>', () => {
|
|||
</script>
|
||||
<script setup lang="ts">
|
||||
enum Foo { A = 123 }
|
||||
</script>`
|
||||
</script>`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
D: BindingTypes.LITERAL_CONST,
|
||||
C: 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">
|
||||
const enum Foo { A = 123 }
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
{ hoistStatic: true },
|
||||
)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
Foo: BindingTypes.LITERAL_CONST
|
||||
Foo: BindingTypes.LITERAL_CONST,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -933,7 +933,7 @@ describe('SFC compile <script setup>', () => {
|
|||
`<script setup lang="ts">
|
||||
import type { Foo } from './main.ts'
|
||||
import { type Bar, Baz } from './main.ts'
|
||||
</script>`
|
||||
</script>`,
|
||||
)
|
||||
expect(content).toMatch(`return { get Baz() { return Baz } }`)
|
||||
assertCode(content)
|
||||
|
@ -1057,7 +1057,7 @@ describe('SFC compile <script setup>', () => {
|
|||
// class method
|
||||
assertAwaitDetection(
|
||||
`const cls = class Foo { async method() { await bar }}`,
|
||||
false
|
||||
false,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -1065,7 +1065,7 @@ describe('SFC compile <script setup>', () => {
|
|||
describe('errors', () => {
|
||||
test('<script> and <script setup> must have same lang', () => {
|
||||
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`)
|
||||
})
|
||||
|
||||
|
@ -1075,20 +1075,20 @@ describe('SFC compile <script setup>', () => {
|
|||
expect(() =>
|
||||
compile(`<script setup>
|
||||
export const a = 1
|
||||
</script>`)
|
||||
</script>`),
|
||||
).toThrow(moduleErrorMsg)
|
||||
|
||||
expect(() =>
|
||||
compile(`<script setup>
|
||||
export * from './foo'
|
||||
</script>`)
|
||||
</script>`),
|
||||
).toThrow(moduleErrorMsg)
|
||||
|
||||
expect(() =>
|
||||
compile(`<script setup>
|
||||
const bar = 1
|
||||
export { bar as default }
|
||||
</script>`)
|
||||
</script>`),
|
||||
).toThrow(moduleErrorMsg)
|
||||
})
|
||||
|
||||
|
@ -1101,14 +1101,14 @@ describe('SFC compile <script setup>', () => {
|
|||
default: () => bar
|
||||
}
|
||||
})
|
||||
</script>`)
|
||||
</script>`),
|
||||
).toThrow(`cannot reference locally declared variables`)
|
||||
|
||||
expect(() =>
|
||||
compile(`<script setup>
|
||||
let bar = 'hello'
|
||||
defineEmits([bar])
|
||||
</script>`)
|
||||
</script>`),
|
||||
).toThrow(`cannot reference locally declared variables`)
|
||||
|
||||
// #4644
|
||||
|
@ -1121,7 +1121,7 @@ describe('SFC compile <script setup>', () => {
|
|||
default: () => bar
|
||||
}
|
||||
})
|
||||
</script>`)
|
||||
</script>`),
|
||||
).not.toThrow(`cannot reference locally declared variables`)
|
||||
})
|
||||
|
||||
|
@ -1137,7 +1137,7 @@ describe('SFC compile <script setup>', () => {
|
|||
defineEmits({
|
||||
foo: bar => bar > 1
|
||||
})
|
||||
</script>`).content
|
||||
</script>`).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1153,7 +1153,7 @@ describe('SFC compile <script setup>', () => {
|
|||
defineEmits({
|
||||
foo: () => bar > 1
|
||||
})
|
||||
</script>`).content
|
||||
</script>`).content,
|
||||
)
|
||||
})
|
||||
})
|
||||
|
@ -1187,7 +1187,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS,
|
||||
bar: BindingTypes.PROPS
|
||||
bar: BindingTypes.PROPS,
|
||||
})
|
||||
expect(bindings!.__isScriptSetup).toBe(false)
|
||||
})
|
||||
|
@ -1211,7 +1211,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
foo: BindingTypes.PROPS,
|
||||
bar: BindingTypes.PROPS,
|
||||
baz: BindingTypes.PROPS,
|
||||
qux: BindingTypes.PROPS
|
||||
qux: BindingTypes.PROPS,
|
||||
})
|
||||
expect(bindings!.__isScriptSetup).toBe(false)
|
||||
})
|
||||
|
@ -1232,7 +1232,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.SETUP_MAYBE_REF,
|
||||
bar: BindingTypes.SETUP_MAYBE_REF
|
||||
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||
})
|
||||
expect(bindings!.__isScriptSetup).toBe(false)
|
||||
})
|
||||
|
@ -1247,7 +1247,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
</script>
|
||||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.LITERAL_CONST
|
||||
foo: BindingTypes.LITERAL_CONST,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1267,7 +1267,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.SETUP_MAYBE_REF,
|
||||
bar: BindingTypes.SETUP_MAYBE_REF
|
||||
bar: BindingTypes.SETUP_MAYBE_REF,
|
||||
})
|
||||
expect(bindings!.__isScriptSetup).toBe(false)
|
||||
})
|
||||
|
@ -1288,7 +1288,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.DATA,
|
||||
bar: BindingTypes.DATA
|
||||
bar: BindingTypes.DATA,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1321,7 +1321,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.OPTIONS,
|
||||
bar: BindingTypes.OPTIONS
|
||||
bar: BindingTypes.OPTIONS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1335,7 +1335,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.OPTIONS,
|
||||
bar: BindingTypes.OPTIONS
|
||||
bar: BindingTypes.OPTIONS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1352,7 +1352,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.OPTIONS,
|
||||
bar: BindingTypes.OPTIONS
|
||||
bar: BindingTypes.OPTIONS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1389,7 +1389,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
baz: BindingTypes.SETUP_MAYBE_REF,
|
||||
qux: BindingTypes.DATA,
|
||||
quux: BindingTypes.OPTIONS,
|
||||
quuz: BindingTypes.OPTIONS
|
||||
quuz: BindingTypes.OPTIONS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1416,7 +1416,7 @@ describe('SFC analyze <script> bindings', () => {
|
|||
c: BindingTypes.LITERAL_CONST,
|
||||
d: BindingTypes.SETUP_MAYBE_REF,
|
||||
e: BindingTypes.SETUP_LET,
|
||||
foo: BindingTypes.PROPS
|
||||
foo: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1427,8 +1427,8 @@ describe('SFC analyze <script> bindings', () => {
|
|||
<template>{{ a }}</template>`,
|
||||
undefined,
|
||||
{
|
||||
filename: 'FooBar.vue'
|
||||
}
|
||||
filename: 'FooBar.vue',
|
||||
},
|
||||
)
|
||||
expect(content).toMatch(`export default {
|
||||
__name: 'FooBar'`)
|
||||
|
@ -1446,8 +1446,8 @@ describe('SFC analyze <script> bindings', () => {
|
|||
<template>{{ a }}</template>`,
|
||||
undefined,
|
||||
{
|
||||
filename: 'FooBar.vue'
|
||||
}
|
||||
filename: 'FooBar.vue',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch(`name: 'FooBar'`)
|
||||
expect(content).toMatch(`name: 'Baz'`)
|
||||
|
@ -1466,8 +1466,8 @@ describe('SFC analyze <script> bindings', () => {
|
|||
<template>{{ a }}</template>`,
|
||||
undefined,
|
||||
{
|
||||
filename: 'FooBar.vue'
|
||||
}
|
||||
filename: 'FooBar.vue',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch(`name: 'FooBar'`)
|
||||
expect(content).toMatch(`name: 'Baz'`)
|
||||
|
@ -1483,8 +1483,8 @@ describe('SFC genDefaultAs', () => {
|
|||
export default {}
|
||||
</script>`,
|
||||
{
|
||||
genDefaultAs: '_sfc_'
|
||||
}
|
||||
genDefaultAs: '_sfc_',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch('export default')
|
||||
expect(content).toMatch(`const _sfc_ = {}`)
|
||||
|
@ -1500,8 +1500,8 @@ describe('SFC genDefaultAs', () => {
|
|||
.foo { color: v-bind(x) }
|
||||
</style>`,
|
||||
{
|
||||
genDefaultAs: '_sfc_'
|
||||
}
|
||||
genDefaultAs: '_sfc_',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch('export default')
|
||||
expect(content).not.toMatch('__default__')
|
||||
|
@ -1518,12 +1518,12 @@ describe('SFC genDefaultAs', () => {
|
|||
const a = 1
|
||||
</script>`,
|
||||
{
|
||||
genDefaultAs: '_sfc_'
|
||||
}
|
||||
genDefaultAs: '_sfc_',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch('export default')
|
||||
expect(content).toMatch(
|
||||
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`
|
||||
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -1537,12 +1537,12 @@ describe('SFC genDefaultAs', () => {
|
|||
const a = 1
|
||||
</script>`,
|
||||
{
|
||||
genDefaultAs: '_sfc_'
|
||||
}
|
||||
genDefaultAs: '_sfc_',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch('export default')
|
||||
expect(content).toMatch(
|
||||
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`
|
||||
`const _sfc_ = /*#__PURE__*/Object.assign(__default__`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -1553,8 +1553,8 @@ describe('SFC genDefaultAs', () => {
|
|||
const a = 1
|
||||
</script>`,
|
||||
{
|
||||
genDefaultAs: '_sfc_'
|
||||
}
|
||||
genDefaultAs: '_sfc_',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch('export default')
|
||||
expect(content).toMatch(`const _sfc_ = {\n setup`)
|
||||
|
@ -1567,8 +1567,8 @@ describe('SFC genDefaultAs', () => {
|
|||
const a = 1
|
||||
</script>`,
|
||||
{
|
||||
genDefaultAs: '_sfc_'
|
||||
}
|
||||
genDefaultAs: '_sfc_',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch('export default')
|
||||
expect(content).toMatch(`const _sfc_ = /*#__PURE__*/_defineComponent(`)
|
||||
|
@ -1584,12 +1584,12 @@ describe('SFC genDefaultAs', () => {
|
|||
const a = 1
|
||||
</script>`,
|
||||
{
|
||||
genDefaultAs: '_sfc_'
|
||||
}
|
||||
genDefaultAs: '_sfc_',
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch('export default')
|
||||
expect(content).toMatch(
|
||||
`const _sfc_ = /*#__PURE__*/_defineComponent({\n ...__default__`
|
||||
`const _sfc_ = /*#__PURE__*/_defineComponent({\n ...__default__`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -1600,12 +1600,12 @@ describe('SFC genDefaultAs', () => {
|
|||
import { toRef } from 'vue'
|
||||
const props = defineProps<{foo: string}>()
|
||||
const foo = toRef(() => props.foo)
|
||||
</script>`
|
||||
</script>`,
|
||||
)
|
||||
expect(bindings).toStrictEqual({
|
||||
toRef: BindingTypes.SETUP_CONST,
|
||||
props: BindingTypes.SETUP_REACTIVE_CONST,
|
||||
foo: BindingTypes.SETUP_REF
|
||||
foo: BindingTypes.SETUP_REF,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -1622,7 +1622,7 @@ describe('SFC genDefaultAs', () => {
|
|||
compile(`
|
||||
<script setup>
|
||||
import { foo } from './foo.js' assert { type: 'foobar' }
|
||||
</script>`)
|
||||
</script>`),
|
||||
).toThrow()
|
||||
})
|
||||
|
||||
|
@ -1635,9 +1635,9 @@ describe('SFC genDefaultAs', () => {
|
|||
`,
|
||||
{
|
||||
babelParserPlugins: [
|
||||
['importAttributes', { deprecatedAssertSyntax: true }]
|
||||
]
|
||||
}
|
||||
['importAttributes', { deprecatedAssertSyntax: true }],
|
||||
],
|
||||
},
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { BindingTypes } from '@vue/compiler-core'
|
||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
||||
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||
|
||||
describe('defineEmits', () => {
|
||||
test('basic usage', () => {
|
||||
|
@ -10,13 +10,13 @@ const myEmit = defineEmits(['foo', 'bar'])
|
|||
`)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
myEmit: BindingTypes.SETUP_CONST
|
||||
myEmit: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
// should remove defineEmits import and call
|
||||
expect(content).not.toMatch('defineEmits')
|
||||
// should generate correct setup signature
|
||||
expect(content).toMatch(
|
||||
`setup(__props, { expose: __expose, emit: __emit }) {`
|
||||
`setup(__props, { expose: __expose, emit: __emit }) {`,
|
||||
)
|
||||
expect(content).toMatch('const myEmit = __emit')
|
||||
// should include context options in default export
|
||||
|
@ -226,9 +226,9 @@ const emit = defineEmits(['a', 'b'])
|
|||
foo: []
|
||||
(e: 'hi'): void
|
||||
}>()
|
||||
</script>`)
|
||||
</script>`),
|
||||
).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()', () => {
|
||||
const { content } = compile(`
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { BindingTypes } from '@vue/compiler-core'
|
||||
import { compileSFCScript as compile, assertCode } from '../utils'
|
||||
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||
|
||||
describe('defineModel()', () => {
|
||||
test('basic usage', () => {
|
||||
|
@ -10,7 +10,7 @@ describe('defineModel()', () => {
|
|||
const c = defineModel('count')
|
||||
const toString = defineModel('toString', { type: Function })
|
||||
</script>
|
||||
`
|
||||
`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch('props: {')
|
||||
|
@ -18,10 +18,10 @@ describe('defineModel()', () => {
|
|||
expect(content).toMatch('"count": {},')
|
||||
expect(content).toMatch('"toString": { type: Function },')
|
||||
expect(content).toMatch(
|
||||
'emits: ["update:modelValue", "update:count", "update:toString"],'
|
||||
'emits: ["update:modelValue", "update:count", "update:toString"],',
|
||||
)
|
||||
expect(content).toMatch(
|
||||
`const modelValue = _useModel(__props, "modelValue")`
|
||||
`const modelValue = _useModel(__props, "modelValue")`,
|
||||
)
|
||||
expect(content).toMatch(`const c = _useModel(__props, "count")`)
|
||||
expect(content).toMatch(`return { modelValue, c, toString }`)
|
||||
|
@ -31,7 +31,7 @@ describe('defineModel()', () => {
|
|||
modelValue: BindingTypes.SETUP_REF,
|
||||
count: BindingTypes.PROPS,
|
||||
c: BindingTypes.SETUP_REF,
|
||||
toString: BindingTypes.SETUP_REF
|
||||
toString: BindingTypes.SETUP_REF,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -43,7 +43,7 @@ describe('defineModel()', () => {
|
|||
defineEmits(['change'])
|
||||
const count = defineModel({ default: 0 })
|
||||
</script>
|
||||
`
|
||||
`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels({ foo: String }`)
|
||||
|
@ -53,7 +53,7 @@ describe('defineModel()', () => {
|
|||
expect(bindings).toStrictEqual({
|
||||
count: BindingTypes.SETUP_REF,
|
||||
foo: BindingTypes.PROPS,
|
||||
modelValue: BindingTypes.PROPS
|
||||
modelValue: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -64,7 +64,7 @@ describe('defineModel()', () => {
|
|||
defineProps(['foo', 'bar'])
|
||||
const count = defineModel('count')
|
||||
</script>
|
||||
`
|
||||
`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`props: /*#__PURE__*/_mergeModels(['foo', 'bar'], {
|
||||
|
@ -75,7 +75,7 @@ describe('defineModel()', () => {
|
|||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS,
|
||||
bar: BindingTypes.PROPS,
|
||||
count: BindingTypes.SETUP_REF
|
||||
count: BindingTypes.SETUP_REF,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -91,7 +91,7 @@ describe('defineModel()', () => {
|
|||
|
||||
const local = true
|
||||
const hoist = defineModel('hoist', { local })
|
||||
</script>`
|
||||
</script>`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`_useModel(__props, "modelValue", { local: true })`)
|
||||
|
@ -111,21 +111,21 @@ describe('defineModel()', () => {
|
|||
const disabled = defineModel<number>('disabled', { required: false })
|
||||
const any = defineModel<any | boolean>('any')
|
||||
</script>
|
||||
`
|
||||
`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch('"modelValue": { type: [Boolean, String] }')
|
||||
expect(content).toMatch('"count": { type: Number }')
|
||||
expect(content).toMatch(
|
||||
'"disabled": { type: Number, ...{ required: false } }'
|
||||
'"disabled": { type: Number, ...{ required: false } }',
|
||||
)
|
||||
expect(content).toMatch('"any": { type: Boolean, skipCheck: true }')
|
||||
expect(content).toMatch(
|
||||
'emits: ["update:modelValue", "update:count", "update:disabled", "update:any"]'
|
||||
'emits: ["update:modelValue", "update:count", "update:disabled", "update:any"]',
|
||||
)
|
||||
|
||||
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 disabled = _useModel(__props, "disabled")`)
|
||||
|
@ -135,7 +135,7 @@ describe('defineModel()', () => {
|
|||
modelValue: BindingTypes.SETUP_REF,
|
||||
count: 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 })
|
||||
</script>
|
||||
`,
|
||||
{ isProd: true }
|
||||
{ isProd: true },
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch('"modelValue": { type: Boolean }')
|
||||
expect(content).toMatch('"fn": {}')
|
||||
expect(content).toMatch(
|
||||
'"fnWithDefault": { type: Function, ...{ default: () => null } },'
|
||||
'"fnWithDefault": { type: Function, ...{ default: () => null } },',
|
||||
)
|
||||
expect(content).toMatch('"str": {}')
|
||||
expect(content).toMatch('"optional": { required: false }')
|
||||
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(
|
||||
`const modelValue = _useModel(__props, "modelValue")`
|
||||
`const modelValue = _useModel(__props, "modelValue")`,
|
||||
)
|
||||
expect(content).toMatch(`const fn = _useModel(__props, "fn")`)
|
||||
expect(content).toMatch(`const str = _useModel(__props, "str")`)
|
||||
|
@ -173,7 +173,7 @@ describe('defineModel()', () => {
|
|||
fn: BindingTypes.SETUP_REF,
|
||||
fnWithDefault: 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()', () => {
|
||||
test('basic usage', () => {
|
||||
|
@ -12,7 +12,7 @@ describe('defineOptions()', () => {
|
|||
expect(content).not.toMatch('defineOptions')
|
||||
// should include context options in default export
|
||||
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: 'BarApp' })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).toThrowError('[@vue/compiler-sfc] duplicate defineOptions() call')
|
||||
})
|
||||
|
||||
|
@ -45,9 +45,9 @@ describe('defineOptions()', () => {
|
|||
<script setup>
|
||||
defineOptions({ props: { foo: String } })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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(() =>
|
||||
|
@ -55,9 +55,9 @@ describe('defineOptions()', () => {
|
|||
<script setup>
|
||||
defineOptions({ emits: ['update'] })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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(() =>
|
||||
|
@ -65,9 +65,9 @@ describe('defineOptions()', () => {
|
|||
<script setup>
|
||||
defineOptions({ expose: ['foo'] })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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(() =>
|
||||
|
@ -75,9 +75,9 @@ describe('defineOptions()', () => {
|
|||
<script setup>
|
||||
defineOptions({ slots: ['foo'] })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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">
|
||||
defineOptions<{ name: 'FooApp' }>()
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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">
|
||||
defineOptions({ props: [] } as any)
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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>
|
||||
defineOptions({ props: ['foo'] })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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(() =>
|
||||
|
@ -121,9 +121,9 @@ describe('defineOptions()', () => {
|
|||
<script setup>
|
||||
defineOptions({ emits: ['update'] })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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(() =>
|
||||
|
@ -131,9 +131,9 @@ describe('defineOptions()', () => {
|
|||
<script setup>
|
||||
defineOptions({ expose: ['foo'] })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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(() =>
|
||||
|
@ -141,9 +141,9 @@ describe('defineOptions()', () => {
|
|||
<script setup lang="ts">
|
||||
defineOptions({ slots: Object })
|
||||
</script>
|
||||
`)
|
||||
`),
|
||||
).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 { compileSFCScript as compile, assertCode } from '../utils'
|
||||
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||
|
||||
describe('defineProps', () => {
|
||||
test('basic usage', () => {
|
||||
|
@ -17,7 +17,7 @@ const bar = 1
|
|||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS,
|
||||
bar: BindingTypes.LITERAL_CONST,
|
||||
props: BindingTypes.SETUP_REACTIVE_CONST
|
||||
props: BindingTypes.SETUP_REACTIVE_CONST,
|
||||
})
|
||||
|
||||
// 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(`error: { type: Error, required: true }`)
|
||||
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(
|
||||
`exclude: { type: [Number, Boolean], required: true }`
|
||||
`exclude: { type: [Number, Boolean], required: true }`,
|
||||
)
|
||||
expect(content).toMatch(`uppercase: { type: String, 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(`literalUnion: { type: String, required: true }`)
|
||||
expect(content).toMatch(
|
||||
`literalUnionNumber: { type: Number, required: true }`
|
||||
`literalUnionNumber: { type: Number, required: true }`,
|
||||
)
|
||||
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(`intersection2: { type: String, required: true }`)
|
||||
|
@ -171,13 +171,13 @@ const props = defineProps({ foo: String })
|
|||
expect(content).toMatch(`unknownUnion: { type: null, required: true }`)
|
||||
// intersection containing unknown type: narrow to the known types
|
||||
expect(content).toMatch(
|
||||
`unknownIntersection: { type: Object, required: true },`
|
||||
`unknownIntersection: { type: Object, required: true },`,
|
||||
)
|
||||
expect(content).toMatch(
|
||||
`unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },`
|
||||
`unknownUnionWithBoolean: { type: Boolean, required: true, skipCheck: true },`,
|
||||
)
|
||||
expect(content).toMatch(
|
||||
`unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }`
|
||||
`unknownUnionWithFunction: { type: Function, required: true, skipCheck: true }`,
|
||||
)
|
||||
expect(bindings).toStrictEqual({
|
||||
string: BindingTypes.PROPS,
|
||||
|
@ -218,7 +218,7 @@ const props = defineProps({ foo: String })
|
|||
unknownUnion: BindingTypes.PROPS,
|
||||
unknownIntersection: BindingTypes.PROPS,
|
||||
unknownUnionWithBoolean: BindingTypes.PROPS,
|
||||
unknownUnionWithFunction: BindingTypes.PROPS
|
||||
unknownUnionWithFunction: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -232,7 +232,7 @@ const props = defineProps({ foo: String })
|
|||
assertCode(content)
|
||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||
expect(bindings).toStrictEqual({
|
||||
x: BindingTypes.PROPS
|
||||
x: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -257,7 +257,7 @@ const props = defineProps({ foo: String })
|
|||
expect(bindings).toStrictEqual({
|
||||
x: BindingTypes.PROPS,
|
||||
y: BindingTypes.PROPS,
|
||||
z: BindingTypes.PROPS
|
||||
z: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -271,7 +271,7 @@ const props = defineProps({ foo: String })
|
|||
assertCode(content)
|
||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||
expect(bindings).toStrictEqual({
|
||||
x: BindingTypes.PROPS
|
||||
x: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -287,7 +287,7 @@ const props = defineProps({ foo: String })
|
|||
assertCode(content)
|
||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||
expect(bindings).toStrictEqual({
|
||||
x: BindingTypes.PROPS
|
||||
x: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -301,7 +301,7 @@ const props = defineProps({ foo: String })
|
|||
assertCode(content)
|
||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||
expect(bindings).toStrictEqual({
|
||||
x: BindingTypes.PROPS
|
||||
x: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -315,7 +315,7 @@ const props = defineProps({ foo: String })
|
|||
assertCode(content)
|
||||
expect(content).toMatch(`x: { type: Number, required: false }`)
|
||||
expect(bindings).toStrictEqual({
|
||||
x: BindingTypes.PROPS
|
||||
x: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -328,7 +328,7 @@ const props = defineProps({ foo: String })
|
|||
expect(content).toMatch(`props: ['foo']`)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS
|
||||
foo: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -354,21 +354,21 @@ const props = defineProps({ foo: String })
|
|||
`)
|
||||
assertCode(content)
|
||||
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(`baz: { type: Boolean, required: true }`)
|
||||
expect(content).toMatch(
|
||||
`qux: { type: Function, required: false, default() { return 1 } }`
|
||||
`qux: { type: Function, required: false, default() { return 1 } }`,
|
||||
)
|
||||
expect(content).toMatch(
|
||||
`quux: { type: Function, required: false, default() { } }`
|
||||
`quux: { type: Function, required: false, default() { } }`,
|
||||
)
|
||||
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(
|
||||
`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(bindings).toStrictEqual({
|
||||
|
@ -379,7 +379,7 @@ const props = defineProps({ foo: String })
|
|||
quux: BindingTypes.PROPS,
|
||||
quuxx: BindingTypes.PROPS,
|
||||
fred: BindingTypes.PROPS,
|
||||
props: BindingTypes.SETUP_CONST
|
||||
props: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -415,7 +415,7 @@ const props = defineProps({ foo: String })
|
|||
})
|
||||
</script>
|
||||
`,
|
||||
{ isProd: true }
|
||||
{ isProd: true },
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`const props = __props`)
|
||||
|
@ -446,7 +446,7 @@ const props = defineProps({ foo: String })
|
|||
foo: { type: String, required: false },
|
||||
bar: { type: Number, required: false },
|
||||
baz: { type: Boolean, required: true }
|
||||
}, { ...defaults })`.trim()
|
||||
}, { ...defaults })`.trim(),
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -469,7 +469,7 @@ const props = defineProps({ foo: String })
|
|||
foo: { type: String, required: false },
|
||||
bar: { type: Number, required: false },
|
||||
baz: { type: Boolean, required: true }
|
||||
}, defaults)`.trim()
|
||||
}, defaults)`.trim(),
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -487,7 +487,7 @@ const props = defineProps({ foo: String })
|
|||
}>(), { ...defaults })
|
||||
</script>
|
||||
`,
|
||||
{ isProd: true }
|
||||
{ isProd: true },
|
||||
)
|
||||
assertCode(content)
|
||||
expect(content).toMatch(`import { mergeDefaults as _mergeDefaults`)
|
||||
|
@ -498,7 +498,7 @@ const props = defineProps({ foo: String })
|
|||
bar: { type: Boolean },
|
||||
baz: { type: [Boolean, Function] },
|
||||
qux: {}
|
||||
}, { ...defaults })`.trim()
|
||||
}, { ...defaults })`.trim(),
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -520,7 +520,7 @@ const props = defineProps({ foo: String })
|
|||
foo: { type: Function, required: false }
|
||||
}, {
|
||||
['fo' + 'o']() { return 'foo' }
|
||||
})`.trim()
|
||||
})`.trim(),
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -533,8 +533,8 @@ const props = defineProps({ foo: String })
|
|||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
{ hoistStatic: true },
|
||||
).content,
|
||||
).toMatch(`foo: { type: Number`)
|
||||
|
||||
expect(
|
||||
|
@ -545,8 +545,8 @@ const props = defineProps({ foo: String })
|
|||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
{ hoistStatic: true },
|
||||
).content,
|
||||
).toMatch(`foo: { type: String`)
|
||||
|
||||
expect(
|
||||
|
@ -557,8 +557,8 @@ const props = defineProps({ foo: String })
|
|||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
{ hoistStatic: true },
|
||||
).content,
|
||||
).toMatch(`foo: { type: [String, Number]`)
|
||||
|
||||
expect(
|
||||
|
@ -569,8 +569,8 @@ const props = defineProps({ foo: String })
|
|||
foo: Foo
|
||||
}>()
|
||||
</script>`,
|
||||
{ hoistStatic: true }
|
||||
).content
|
||||
{ hoistStatic: true },
|
||||
).content,
|
||||
).toMatch(`foo: { type: Number`)
|
||||
})
|
||||
|
||||
|
@ -585,7 +585,7 @@ const props = defineProps({ foo: String })
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
bar: BindingTypes.SETUP_REF,
|
||||
computed: BindingTypes.SETUP_CONST
|
||||
computed: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -596,7 +596,7 @@ const props = defineProps({ foo: String })
|
|||
const { foo } = defineProps<{
|
||||
foo: Foo
|
||||
}>()
|
||||
</script>`
|
||||
</script>`,
|
||||
)
|
||||
expect(content).toMatch(`const { foo } = __props`)
|
||||
assertCode(content)
|
||||
|
@ -649,7 +649,7 @@ const props = defineProps({ foo: String })
|
|||
assertCode(content)
|
||||
expect(content).toMatch(`"spa ce": { type: null, required: true }`)
|
||||
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(`"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(`"at@sign": { type: null, required: true }`)
|
||||
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(`"ca^ret": { type: null, required: true }`)
|
||||
|
@ -707,7 +707,7 @@ const props = defineProps({ foo: String })
|
|||
'curly{bra}ces': BindingTypes.PROPS,
|
||||
'pi|pe': 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}>()
|
||||
</script>`,
|
||||
{ isProd: true, customElement: filename => /\.ce\.vue$/.test(filename) },
|
||||
{ filename: 'app.ce.vue' }
|
||||
{ filename: 'app.ce.vue' },
|
||||
)
|
||||
|
||||
expect(content).toMatch(`foo: {type: Number}`)
|
||||
|
@ -736,7 +736,7 @@ const props = defineProps({ foo: String })
|
|||
});
|
||||
</script>`,
|
||||
{ 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 }`)
|
||||
assertCode(content)
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { BindingTypes } from '@vue/compiler-core'
|
||||
import { SFCScriptCompileOptions } from '../../src'
|
||||
import { compileSFCScript, assertCode } from '../utils'
|
||||
import type { SFCScriptCompileOptions } from '../../src'
|
||||
import { assertCode, compileSFCScript } from '../utils'
|
||||
|
||||
describe('sfc reactive props destructure', () => {
|
||||
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
||||
return compileSFCScript(src, {
|
||||
inlineTemplate: true,
|
||||
propsDestructure: true,
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ describe('sfc reactive props destructure', () => {
|
|||
expect(content).toMatch(`_toDisplayString(__props.foo)`)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS
|
||||
foo: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -44,7 +44,7 @@ describe('sfc reactive props destructure', () => {
|
|||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS,
|
||||
bar: BindingTypes.LITERAL_CONST,
|
||||
hello: BindingTypes.LITERAL_CONST
|
||||
hello: BindingTypes.LITERAL_CONST,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -65,7 +65,7 @@ describe('sfc reactive props destructure', () => {
|
|||
expect(bindings).toStrictEqual({
|
||||
foo: 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({
|
||||
__propsAliases: {
|
||||
fooBar: 'foo:bar'
|
||||
fooBar: 'foo:bar',
|
||||
},
|
||||
foo: BindingTypes.PROPS,
|
||||
'foo:bar': BindingTypes.PROPS,
|
||||
fooBar: BindingTypes.PROPS_ALIASED
|
||||
fooBar: BindingTypes.PROPS_ALIASED,
|
||||
})
|
||||
|
||||
expect(content).toMatch(`
|
||||
|
@ -159,13 +159,13 @@ describe('sfc reactive props destructure', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
__propsAliases: {
|
||||
fooBar: 'foo:bar'
|
||||
fooBar: 'foo:bar',
|
||||
},
|
||||
foo: BindingTypes.PROPS,
|
||||
bar: BindingTypes.PROPS,
|
||||
'foo:bar': BindingTypes.PROPS,
|
||||
fooBar: BindingTypes.PROPS_ALIASED,
|
||||
'onUpdate:modelValue': BindingTypes.PROPS
|
||||
'onUpdate:modelValue': BindingTypes.PROPS,
|
||||
})
|
||||
expect(content).toMatch(`
|
||||
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 }>()
|
||||
</script>
|
||||
`,
|
||||
{ isProd: true }
|
||||
{ isProd: true },
|
||||
)
|
||||
assertCode(content)
|
||||
// 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,
|
||||
bar: BindingTypes.PROPS_ALIASED,
|
||||
__propsAliases: {
|
||||
bar: 'foo'
|
||||
}
|
||||
bar: 'foo',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -242,8 +242,8 @@ describe('sfc reactive props destructure', () => {
|
|||
'foo.bar': BindingTypes.PROPS,
|
||||
fooBar: BindingTypes.PROPS_ALIASED,
|
||||
__propsAliases: {
|
||||
fooBar: 'foo.bar'
|
||||
}
|
||||
fooBar: 'foo.bar',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -254,14 +254,14 @@ describe('sfc reactive props destructure', () => {
|
|||
</script>
|
||||
`)
|
||||
expect(content).toMatch(
|
||||
`const rest = _createPropsRestProxy(__props, ["foo","bar"])`
|
||||
`const rest = _createPropsRestProxy(__props, ["foo","bar"])`,
|
||||
)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS,
|
||||
bar: 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)`)
|
||||
assertCode(content)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS
|
||||
foo: BindingTypes.PROPS,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -339,22 +339,22 @@ describe('sfc reactive props destructure', () => {
|
|||
test('should error on deep destructure', () => {
|
||||
expect(() =>
|
||||
compile(
|
||||
`<script setup>const { foo: [bar] } = defineProps(['foo'])</script>`
|
||||
)
|
||||
`<script setup>const { foo: [bar] } = defineProps(['foo'])</script>`,
|
||||
),
|
||||
).toThrow(`destructure does not support nested patterns`)
|
||||
|
||||
expect(() =>
|
||||
compile(
|
||||
`<script setup>const { foo: { bar } } = defineProps(['foo'])</script>`
|
||||
)
|
||||
`<script setup>const { foo: { bar } } = defineProps(['foo'])</script>`,
|
||||
),
|
||||
).toThrow(`destructure does not support nested patterns`)
|
||||
})
|
||||
|
||||
test('should error on computed key', () => {
|
||||
expect(() =>
|
||||
compile(
|
||||
`<script setup>const { [foo]: bar } = defineProps(['foo'])</script>`
|
||||
)
|
||||
`<script setup>const { [foo]: bar } = defineProps(['foo'])</script>`,
|
||||
),
|
||||
).toThrow(`destructure cannot use computed key`)
|
||||
})
|
||||
|
||||
|
@ -363,8 +363,8 @@ describe('sfc reactive props destructure', () => {
|
|||
compile(
|
||||
`<script setup lang="ts">
|
||||
const { foo } = withDefaults(defineProps<{ foo: string }>(), { foo: 'foo' })
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).toThrow(`withDefaults() is unnecessary when using destructure`)
|
||||
})
|
||||
|
||||
|
@ -376,8 +376,8 @@ describe('sfc reactive props destructure', () => {
|
|||
const {
|
||||
foo = () => x
|
||||
} = defineProps(['foo'])
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).toThrow(`cannot reference locally declared variables`)
|
||||
})
|
||||
|
||||
|
@ -387,8 +387,8 @@ describe('sfc reactive props destructure', () => {
|
|||
`<script setup>
|
||||
const { foo } = defineProps(['foo'])
|
||||
foo = 'bar'
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).toThrow(`Cannot assign to destructured props`)
|
||||
|
||||
expect(() =>
|
||||
|
@ -396,8 +396,8 @@ describe('sfc reactive props destructure', () => {
|
|||
`<script setup>
|
||||
let { foo } = defineProps(['foo'])
|
||||
foo = 'bar'
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).toThrow(`Cannot assign to destructured props`)
|
||||
})
|
||||
|
||||
|
@ -408,10 +408,10 @@ describe('sfc reactive props destructure', () => {
|
|||
import { watch } from 'vue'
|
||||
const { foo } = defineProps(['foo'])
|
||||
watch(foo, () => {})
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).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(() =>
|
||||
|
@ -420,10 +420,10 @@ describe('sfc reactive props destructure', () => {
|
|||
import { watch as w } from 'vue'
|
||||
const { foo } = defineProps(['foo'])
|
||||
w(foo, () => {})
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).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(() =>
|
||||
|
@ -432,10 +432,10 @@ describe('sfc reactive props destructure', () => {
|
|||
import { toRef } from 'vue'
|
||||
const { foo } = defineProps(['foo'])
|
||||
toRef(foo)
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).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(() =>
|
||||
|
@ -444,10 +444,10 @@ describe('sfc reactive props destructure', () => {
|
|||
import { toRef as r } from 'vue'
|
||||
const { foo } = defineProps(['foo'])
|
||||
r(foo)
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).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(
|
||||
`<script setup lang="ts">
|
||||
const { foo = 'hello' } = defineProps<{ foo?: number }>()
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).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();
|
||||
watch(e, () => {});
|
||||
watch(info, () => {});
|
||||
</script>`
|
||||
)
|
||||
</script>`,
|
||||
),
|
||||
).not.toThrowError()
|
||||
})
|
||||
})
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { compileSFCScript as compile, assertCode } from '../utils'
|
||||
import { assertCode, compileSFCScript as compile } from '../utils'
|
||||
|
||||
describe('defineSlots()', () => {
|
||||
test('basic usage', () => {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { BindingTypes } from '@vue/compiler-core'
|
||||
import { SFCScriptCompileOptions } from '../../src'
|
||||
import { compileSFCScript, assertCode } from '../utils'
|
||||
import type { SFCScriptCompileOptions } from '../../src'
|
||||
import { assertCode, compileSFCScript } from '../utils'
|
||||
|
||||
describe('sfc hoist static', () => {
|
||||
function compile(src: string, options?: Partial<SFCScriptCompileOptions>) {
|
||||
return compileSFCScript(src, {
|
||||
inlineTemplate: true,
|
||||
hoistStatic: true,
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ describe('sfc hoist static', () => {
|
|||
boolean: BindingTypes.LITERAL_CONST,
|
||||
nil: BindingTypes.LITERAL_CONST,
|
||||
bigint: BindingTypes.LITERAL_CONST,
|
||||
template: BindingTypes.LITERAL_CONST
|
||||
template: BindingTypes.LITERAL_CONST,
|
||||
})
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -57,7 +57,7 @@ describe('sfc hoist static', () => {
|
|||
binary: BindingTypes.LITERAL_CONST,
|
||||
conditional: BindingTypes.LITERAL_CONST,
|
||||
unary: BindingTypes.LITERAL_CONST,
|
||||
sequence: BindingTypes.LITERAL_CONST
|
||||
sequence: BindingTypes.LITERAL_CONST,
|
||||
})
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -79,7 +79,7 @@ describe('sfc hoist static', () => {
|
|||
expect(content.startsWith(hoistCode)).toBe(true)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.PROPS,
|
||||
defaultValue: BindingTypes.LITERAL_CONST
|
||||
defaultValue: BindingTypes.LITERAL_CONST,
|
||||
})
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -100,7 +100,7 @@ describe('sfc hoist static', () => {
|
|||
KEY1: BindingTypes.SETUP_LET,
|
||||
KEY2: BindingTypes.SETUP_LET,
|
||||
regex: BindingTypes.SETUP_CONST,
|
||||
undef: BindingTypes.SETUP_MAYBE_REF
|
||||
undef: BindingTypes.SETUP_MAYBE_REF,
|
||||
})
|
||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||
assertCode(content)
|
||||
|
@ -131,7 +131,7 @@ describe('sfc hoist static', () => {
|
|||
KEY4: BindingTypes.SETUP_CONST,
|
||||
KEY5: BindingTypes.SETUP_CONST,
|
||||
KEY6: BindingTypes.SETUP_CONST,
|
||||
i: BindingTypes.SETUP_LET
|
||||
i: BindingTypes.SETUP_LET,
|
||||
})
|
||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||
assertCode(content)
|
||||
|
@ -149,7 +149,7 @@ describe('sfc hoist static', () => {
|
|||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
arr: BindingTypes.SETUP_CONST,
|
||||
obj: BindingTypes.SETUP_CONST
|
||||
obj: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||
assertCode(content)
|
||||
|
@ -169,7 +169,7 @@ describe('sfc hoist static', () => {
|
|||
expect(bindings).toStrictEqual({
|
||||
Foo: BindingTypes.SETUP_CONST,
|
||||
fn: BindingTypes.SETUP_CONST,
|
||||
fn2: BindingTypes.SETUP_CONST
|
||||
fn2: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
expect(content).toMatch(`setup(__props) {\n\n ${code}`)
|
||||
assertCode(content)
|
||||
|
@ -185,7 +185,7 @@ describe('sfc hoist static', () => {
|
|||
</script>
|
||||
`)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.SETUP_CONST
|
||||
foo: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -197,10 +197,10 @@ describe('sfc hoist static', () => {
|
|||
const foo = 'bar'
|
||||
</script>
|
||||
`,
|
||||
{ hoistStatic: false }
|
||||
{ hoistStatic: false },
|
||||
)
|
||||
expect(bindings).toStrictEqual({
|
||||
foo: BindingTypes.SETUP_CONST
|
||||
foo: BindingTypes.SETUP_CONST,
|
||||
})
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -212,7 +212,7 @@ describe('sfc hoist static', () => {
|
|||
const foo = 'bar'
|
||||
</script>
|
||||
<template>{{ foo }}</template>
|
||||
`
|
||||
`,
|
||||
)
|
||||
expect(content).toMatch('_toDisplayString(foo)')
|
||||
})
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
import { normalize } from 'node:path'
|
||||
import { Identifier } from '@babel/types'
|
||||
import { SFCScriptCompileOptions, parse } from '../../src'
|
||||
import type { Identifier } from '@babel/types'
|
||||
import { type SFCScriptCompileOptions, parse } from '../../src'
|
||||
import { ScriptCompileContext } from '../../src/script/context'
|
||||
import {
|
||||
inferRuntimeType,
|
||||
invalidateTypeCache,
|
||||
recordImports,
|
||||
registerTS,
|
||||
resolveTypeElements,
|
||||
registerTS
|
||||
} from '../../src/script/resolveType'
|
||||
|
||||
import ts from 'typescript'
|
||||
|
@ -25,7 +25,7 @@ describe('resolveType', () => {
|
|||
expect(props).toStrictEqual({
|
||||
foo: ['Number'],
|
||||
bar: ['Function'],
|
||||
baz: ['String']
|
||||
baz: ['String'],
|
||||
})
|
||||
expect(calls?.length).toBe(2)
|
||||
})
|
||||
|
@ -35,9 +35,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
type Aliased = { foo: number }
|
||||
defineProps<Aliased>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number']
|
||||
foo: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -46,9 +46,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
export type Aliased = { foo: number }
|
||||
defineProps<Aliased>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number']
|
||||
foo: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -57,9 +57,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
interface Aliased { foo: number }
|
||||
defineProps<Aliased>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number']
|
||||
foo: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -68,9 +68,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
export interface Aliased { foo: number }
|
||||
defineProps<Aliased>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number']
|
||||
foo: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -82,12 +82,12 @@ describe('resolveType', () => {
|
|||
interface C { c: string }
|
||||
interface Aliased extends B, C { foo: number }
|
||||
defineProps<Aliased>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
a: ['Function'],
|
||||
b: ['Boolean'],
|
||||
c: ['String'],
|
||||
foo: ['Number']
|
||||
foo: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -96,9 +96,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
class Foo {}
|
||||
defineProps<{ foo: Foo }>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Object']
|
||||
foo: ['Object'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -106,7 +106,7 @@ describe('resolveType', () => {
|
|||
expect(
|
||||
resolve(`
|
||||
defineProps<(e: 'foo') => void>()
|
||||
`).calls?.length
|
||||
`).calls?.length,
|
||||
).toBe(1)
|
||||
})
|
||||
|
||||
|
@ -115,7 +115,7 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
type Fn = (e: 'foo') => void
|
||||
defineProps<Fn>()
|
||||
`).calls?.length
|
||||
`).calls?.length,
|
||||
).toBe(1)
|
||||
})
|
||||
|
||||
|
@ -126,13 +126,13 @@ describe('resolveType', () => {
|
|||
type Bar = { bar: string }
|
||||
type Baz = { bar: string | boolean }
|
||||
defineProps<{ self: any } & Foo & Bar & Baz>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
self: ['Unknown'],
|
||||
foo: ['Number'],
|
||||
// both Bar & Baz has 'bar', but Baz['bar] is wider so it should be
|
||||
// preferred
|
||||
bar: ['String', 'Boolean']
|
||||
bar: ['String', 'Boolean'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -156,12 +156,12 @@ describe('resolveType', () => {
|
|||
}
|
||||
|
||||
defineProps<CommonProps & ConditionalProps>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
size: ['String'],
|
||||
color: ['String', 'Number'],
|
||||
appearance: ['String'],
|
||||
note: ['String']
|
||||
note: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -173,12 +173,12 @@ describe('resolveType', () => {
|
|||
defineProps<{
|
||||
[\`_\${T}_\${S}_\`]: string
|
||||
}>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
_foo_x_: ['String'],
|
||||
_foo_y_: ['String'],
|
||||
_bar_x_: ['String'],
|
||||
_bar_y_: ['String']
|
||||
_bar_y_: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -195,7 +195,7 @@ describe('resolveType', () => {
|
|||
} & {
|
||||
[K in \`x\${T}\`]: string
|
||||
}>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String', 'Number'],
|
||||
bar: ['String', 'Number'],
|
||||
|
@ -204,7 +204,7 @@ describe('resolveType', () => {
|
|||
FOO: ['String'],
|
||||
xfoo: ['String'],
|
||||
xbar: ['String'],
|
||||
optional: ['Boolean']
|
||||
optional: ['Boolean'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -213,14 +213,14 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
type T = { foo: number, bar: string }
|
||||
defineProps<Partial<T>>()
|
||||
`).raw.props
|
||||
`).raw.props,
|
||||
).toMatchObject({
|
||||
foo: {
|
||||
optional: true
|
||||
optional: true,
|
||||
},
|
||||
bar: {
|
||||
optional: true
|
||||
}
|
||||
optional: true,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -229,14 +229,14 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
type T = { foo?: number, bar?: string }
|
||||
defineProps<Required<T>>()
|
||||
`).raw.props
|
||||
`).raw.props,
|
||||
).toMatchObject({
|
||||
foo: {
|
||||
optional: false
|
||||
optional: false,
|
||||
},
|
||||
bar: {
|
||||
optional: false
|
||||
}
|
||||
optional: false,
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -246,10 +246,10 @@ describe('resolveType', () => {
|
|||
type T = { foo: number, bar: string, baz: boolean }
|
||||
type K = 'foo' | 'bar'
|
||||
defineProps<Pick<T, K>>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -259,9 +259,9 @@ describe('resolveType', () => {
|
|||
type T = { foo: number, bar: string, baz: boolean }
|
||||
type K = 'foo' | 'bar'
|
||||
defineProps<Omit<T, K>>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
baz: ['Boolean']
|
||||
baz: ['Boolean'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -271,9 +271,9 @@ describe('resolveType', () => {
|
|||
type T = { bar: number }
|
||||
type S = { nested: { foo: T['bar'] }}
|
||||
defineProps<S['nested']>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number']
|
||||
foo: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -284,10 +284,10 @@ describe('resolveType', () => {
|
|||
type T = { foo: string, bar: number }
|
||||
type S = { foo: { foo: T[string] }, bar: { bar: string } }
|
||||
defineProps<S[K]>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String', 'Number'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -299,12 +299,12 @@ describe('resolveType', () => {
|
|||
type T = [1, 'foo']
|
||||
type TT = [foo: 1, bar: 'foo']
|
||||
defineProps<{ foo: A[number], bar: AA[number], tuple: T[number], namedTuple: TT[number] }>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String', 'Number'],
|
||||
bar: ['String'],
|
||||
tuple: ['Number', 'String'],
|
||||
namedTuple: ['Number', 'String']
|
||||
namedTuple: ['Number', 'String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -321,9 +321,9 @@ describe('resolveType', () => {
|
|||
}
|
||||
}
|
||||
defineProps<Foo.Bar.A>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number']
|
||||
foo: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -340,10 +340,10 @@ describe('resolveType', () => {
|
|||
foo: Foo['a'],
|
||||
bar: Foo['b']
|
||||
}>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number']
|
||||
bar: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -360,10 +360,10 @@ describe('resolveType', () => {
|
|||
foo: Foo.A,
|
||||
bar: Foo.B
|
||||
}>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number']
|
||||
bar: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -380,10 +380,10 @@ describe('resolveType', () => {
|
|||
foo: Foo.A,
|
||||
bar: Foo['b']
|
||||
}>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number']
|
||||
bar: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -399,9 +399,9 @@ describe('resolveType', () => {
|
|||
defineProps<{
|
||||
foo: Foo
|
||||
}>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['Number', 'String']
|
||||
foo: ['Number', 'String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -410,9 +410,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
declare const a: string
|
||||
defineProps<{ foo: typeof a }>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -429,11 +429,11 @@ describe('resolveType', () => {
|
|||
}
|
||||
type Props = ExtractPropTypes<typeof props>
|
||||
defineProps<Props>()
|
||||
`
|
||||
`,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Boolean']
|
||||
bar: ['Boolean'],
|
||||
})
|
||||
expect(raw.props.bar.optional).toBe(false)
|
||||
})
|
||||
|
@ -447,11 +447,11 @@ describe('resolveType', () => {
|
|||
}
|
||||
type Props = Partial<import('vue').ExtractPropTypes<ReturnType<typeof props>>>
|
||||
defineProps<Props>()
|
||||
`
|
||||
`,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Boolean']
|
||||
bar: ['Boolean'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -461,9 +461,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
type Props<T> = T
|
||||
defineProps<Props<{ foo: string }>>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -474,11 +474,11 @@ describe('resolveType', () => {
|
|||
type Bar = { bar: number; }
|
||||
type Props<T,U> = T & U & { baz: boolean }
|
||||
defineProps<Props<Foo, Bar>>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number'],
|
||||
baz: ['Boolean']
|
||||
baz: ['Boolean'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -489,9 +489,9 @@ describe('resolveType', () => {
|
|||
type Props<T> = Aliased<T>
|
||||
type Foo = { foo: string; }
|
||||
defineProps<Props<Foo>>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -500,9 +500,9 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
type Aliased<T> = { foo: T }
|
||||
defineProps<Aliased<string>>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -514,25 +514,25 @@ describe('resolveType', () => {
|
|||
}
|
||||
type Foo = string
|
||||
defineProps<Props<Foo>>()
|
||||
`).props
|
||||
`).props,
|
||||
).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
})
|
||||
|
||||
test('generic from external-file', () => {
|
||||
const files = {
|
||||
'/foo.ts': 'export type P<T> = { foo: T }'
|
||||
'/foo.ts': 'export type P<T> = { foo: T }',
|
||||
}
|
||||
const { props } = resolve(
|
||||
`
|
||||
import { P } from './foo'
|
||||
defineProps<P<string>>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -544,7 +544,7 @@ describe('resolveType', () => {
|
|||
'/bar.d.ts':
|
||||
'type X = { bar: string }; export { X as Y };' +
|
||||
// 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(
|
||||
`
|
||||
|
@ -552,11 +552,11 @@ describe('resolveType', () => {
|
|||
import { Y as PP } from './bar'
|
||||
defineProps<P & PP>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['Number'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -568,7 +568,7 @@ describe('resolveType', () => {
|
|||
'type X = { bar: string }; export { X as Y };' +
|
||||
// verify that we can parse syntax that is only valid in d.ts
|
||||
'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(
|
||||
`
|
||||
|
@ -579,32 +579,32 @@ describe('resolveType', () => {
|
|||
`,
|
||||
files,
|
||||
{},
|
||||
'C:\\Test\\FolderA\\Test.vue'
|
||||
'C:\\Test\\FolderA\\Test.vue',
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['Number'],
|
||||
bar: ['String'],
|
||||
buz: ['String']
|
||||
buz: ['String'],
|
||||
})
|
||||
expect(deps && [...deps].map(normalize)).toStrictEqual(
|
||||
Object.keys(files).map(normalize)
|
||||
Object.keys(files).map(normalize),
|
||||
)
|
||||
})
|
||||
|
||||
// #8244
|
||||
test('utility type in external file', () => {
|
||||
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(
|
||||
`
|
||||
import { B } from './foo'
|
||||
defineProps<B>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
n: ['Number']
|
||||
n: ['Number'],
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -613,7 +613,7 @@ describe('resolveType', () => {
|
|||
'/foo.vue':
|
||||
'<script lang="ts">export type P = { foo: number }</script>',
|
||||
'/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(
|
||||
`
|
||||
|
@ -621,11 +621,11 @@ describe('resolveType', () => {
|
|||
import { P as PP } from './bar.vue'
|
||||
defineProps<P & PP>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['Number'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -635,18 +635,18 @@ describe('resolveType', () => {
|
|||
'/foo.ts': `import type { P as PP } from './nested/bar.vue'
|
||||
export type P = { foo: number } & PP`,
|
||||
'/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(
|
||||
`
|
||||
import { P } from './foo'
|
||||
defineProps<P>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['Number'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -654,17 +654,17 @@ describe('resolveType', () => {
|
|||
test('relative (chained, re-export)', () => {
|
||||
const files = {
|
||||
'/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(
|
||||
`
|
||||
import { PP as P } from './foo'
|
||||
defineProps<P>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -672,17 +672,17 @@ describe('resolveType', () => {
|
|||
test('relative (chained, export *)', () => {
|
||||
const files = {
|
||||
'/foo.ts': `export * from './bar'`,
|
||||
'/bar.ts': 'export type P = { bar: string }'
|
||||
'/bar.ts': 'export type P = { bar: string }',
|
||||
}
|
||||
const { props, deps } = resolve(
|
||||
`
|
||||
import { P } from './foo'
|
||||
defineProps<P>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -690,7 +690,7 @@ describe('resolveType', () => {
|
|||
test('relative (default export)', () => {
|
||||
const files = {
|
||||
'/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(
|
||||
`
|
||||
|
@ -698,11 +698,11 @@ describe('resolveType', () => {
|
|||
import X from './bar'
|
||||
defineProps<P & X>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -711,7 +711,7 @@ describe('resolveType', () => {
|
|||
const files = {
|
||||
'/bar.ts': `export { default } from './foo'`,
|
||||
'/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(
|
||||
`
|
||||
|
@ -719,11 +719,11 @@ describe('resolveType', () => {
|
|||
import PP from './baz'
|
||||
defineProps<P & PP>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number']
|
||||
bar: ['Number'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -732,17 +732,17 @@ describe('resolveType', () => {
|
|||
const files = {
|
||||
'/foo.ts': `export default interface P { foo: string }`,
|
||||
'/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(
|
||||
`import { X, XX } from './baz'
|
||||
defineProps<X & XX>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number']
|
||||
bar: ['Number'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(['/baz.ts', '/foo.ts', '/bar.ts'])
|
||||
})
|
||||
|
@ -750,17 +750,17 @@ describe('resolveType', () => {
|
|||
test('relative (dynamic import)', () => {
|
||||
const files = {
|
||||
'/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(
|
||||
`
|
||||
defineProps<import('./foo').P>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String'],
|
||||
bar: ['Number']
|
||||
bar: ['Number'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -770,17 +770,17 @@ describe('resolveType', () => {
|
|||
const files = {
|
||||
'/foo.d.ts':
|
||||
'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(
|
||||
`
|
||||
import { P } from './foo'
|
||||
defineProps<P>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -788,17 +788,17 @@ describe('resolveType', () => {
|
|||
test('ts module resolve', () => {
|
||||
const files = {
|
||||
'/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 }',
|
||||
'/tsconfig.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
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(
|
||||
|
@ -807,16 +807,16 @@ describe('resolveType', () => {
|
|||
import { PP } from 'bar'
|
||||
defineProps<P & PP>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
|
||||
expect(props).toStrictEqual({
|
||||
foo: ['Number'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual([
|
||||
'/node_modules/foo/index.d.ts',
|
||||
'/pp.ts'
|
||||
'/pp.ts',
|
||||
])
|
||||
})
|
||||
|
||||
|
@ -825,23 +825,23 @@ describe('resolveType', () => {
|
|||
'/tsconfig.json': JSON.stringify({
|
||||
references: [
|
||||
{
|
||||
path: './tsconfig.app.json'
|
||||
}
|
||||
]
|
||||
path: './tsconfig.app.json',
|
||||
},
|
||||
],
|
||||
}),
|
||||
'/tsconfig.app.json': JSON.stringify({
|
||||
include: ['**/*.ts', '**/*.vue'],
|
||||
extends: './tsconfig.web.json'
|
||||
extends: './tsconfig.web.json',
|
||||
}),
|
||||
'/tsconfig.web.json': JSON.stringify({
|
||||
compilerOptions: {
|
||||
composite: true,
|
||||
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(
|
||||
|
@ -849,11 +849,11 @@ describe('resolveType', () => {
|
|||
import { User } from 'bar'
|
||||
defineProps<User>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
|
||||
expect(props).toStrictEqual({
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(['/user.ts'])
|
||||
})
|
||||
|
@ -864,12 +864,12 @@ describe('resolveType', () => {
|
|||
compilerOptions: {
|
||||
include: ['**/*.ts', '**/*.vue'],
|
||||
paths: {
|
||||
'@/*': ['./src/*']
|
||||
}
|
||||
}
|
||||
'@/*': ['./src/*'],
|
||||
},
|
||||
},
|
||||
}),
|
||||
'/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(
|
||||
|
@ -877,11 +877,11 @@ describe('resolveType', () => {
|
|||
import { P } from '@/Foo.vue'
|
||||
defineProps<P>()
|
||||
`,
|
||||
files
|
||||
files,
|
||||
)
|
||||
|
||||
expect(props).toStrictEqual({
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(['/src/Foo.vue'])
|
||||
})
|
||||
|
@ -898,16 +898,16 @@ describe('resolveType', () => {
|
|||
type PP = { bar: string }
|
||||
}
|
||||
export {}
|
||||
`
|
||||
`,
|
||||
}
|
||||
|
||||
const { props, deps } = resolve(`defineProps<App.User & PP>()`, files, {
|
||||
globalTypeFiles: Object.keys(files)
|
||||
globalTypeFiles: Object.keys(files),
|
||||
})
|
||||
|
||||
expect(props).toStrictEqual({
|
||||
name: ['String'],
|
||||
bar: ['String']
|
||||
bar: ['String'],
|
||||
})
|
||||
expect(deps && [...deps]).toStrictEqual(Object.keys(files))
|
||||
})
|
||||
|
@ -927,33 +927,33 @@ describe('resolveType', () => {
|
|||
id: string
|
||||
}
|
||||
}
|
||||
`
|
||||
`,
|
||||
}
|
||||
|
||||
const { props } = resolve(`defineProps<App.Data.AircraftData>()`, files, {
|
||||
globalTypeFiles: Object.keys(files)
|
||||
globalTypeFiles: Object.keys(files),
|
||||
})
|
||||
|
||||
expect(props).toStrictEqual({
|
||||
id: ['String'],
|
||||
manufacturer: ['Object']
|
||||
manufacturer: ['Object'],
|
||||
})
|
||||
})
|
||||
|
||||
// #9871
|
||||
test('shared generics with different args', () => {
|
||||
const files = {
|
||||
'/foo.ts': `export interface Foo<T> { value: T }`
|
||||
'/foo.ts': `export interface Foo<T> { value: T }`,
|
||||
}
|
||||
const { props } = resolve(
|
||||
`import type { Foo } from './foo'
|
||||
defineProps<Foo<string>>()`,
|
||||
files,
|
||||
undefined,
|
||||
`/One.vue`
|
||||
`/One.vue`,
|
||||
)
|
||||
expect(props).toStrictEqual({
|
||||
value: ['String']
|
||||
value: ['String'],
|
||||
})
|
||||
const { props: props2 } = resolve(
|
||||
`import type { Foo } from './foo'
|
||||
|
@ -961,10 +961,10 @@ describe('resolveType', () => {
|
|||
files,
|
||||
undefined,
|
||||
`/Two.vue`,
|
||||
false /* do not invalidate cache */
|
||||
false /* do not invalidate cache */,
|
||||
)
|
||||
expect(props2).toStrictEqual({
|
||||
value: ['Number']
|
||||
value: ['Number'],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -972,25 +972,25 @@ describe('resolveType', () => {
|
|||
describe('errors', () => {
|
||||
test('failed type reference', () => {
|
||||
expect(() => resolve(`defineProps<X>()`)).toThrow(
|
||||
`Unresolvable type reference`
|
||||
`Unresolvable type reference`,
|
||||
)
|
||||
})
|
||||
|
||||
test('unsupported computed keys', () => {
|
||||
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', () => {
|
||||
expect(() => resolve(`defineProps<X[K]>()`)).toThrow(
|
||||
`Unsupported type when resolving index type`
|
||||
`Unsupported type when resolving index type`,
|
||||
)
|
||||
})
|
||||
|
||||
test('failed import source resolve', () => {
|
||||
expect(() =>
|
||||
resolve(`import { X } from './foo'; defineProps<X>()`)
|
||||
resolve(`import { X } from './foo'; defineProps<X>()`),
|
||||
).toThrow(`Failed to resolve import source "./foo"`)
|
||||
})
|
||||
|
||||
|
@ -1001,7 +1001,7 @@ describe('resolveType', () => {
|
|||
resolve(`
|
||||
import type P from 'unknown'
|
||||
defineProps<{ foo: P }>()
|
||||
`)
|
||||
`),
|
||||
).not.toThrow()
|
||||
})
|
||||
|
||||
|
@ -1011,7 +1011,7 @@ describe('resolveType', () => {
|
|||
import type Base from 'unknown'
|
||||
interface Props extends Base {}
|
||||
defineProps<Props>()
|
||||
`)
|
||||
`),
|
||||
).toThrow(`@vue-ignore`)
|
||||
})
|
||||
|
||||
|
@ -1026,11 +1026,11 @@ describe('resolveType', () => {
|
|||
foo: string
|
||||
}
|
||||
defineProps<Props>()
|
||||
`))
|
||||
`)),
|
||||
).not.toThrow(`@vue-ignore`)
|
||||
|
||||
expect(res.props).toStrictEqual({
|
||||
foo: ['String']
|
||||
foo: ['String'],
|
||||
})
|
||||
})
|
||||
})
|
||||
|
@ -1041,10 +1041,10 @@ function resolve(
|
|||
files: Record<string, string> = {},
|
||||
options?: Partial<SFCScriptCompileOptions>,
|
||||
sourceFileName: string = '/Test.vue',
|
||||
invalidateCache = true
|
||||
invalidateCache = true,
|
||||
) {
|
||||
const { descriptor } = parse(`<script setup lang="ts">\n${code}\n</script>`, {
|
||||
filename: sourceFileName
|
||||
filename: sourceFileName,
|
||||
})
|
||||
const ctx = new ScriptCompileContext(descriptor, {
|
||||
id: 'test',
|
||||
|
@ -1054,9 +1054,9 @@ function resolve(
|
|||
},
|
||||
readFile(file) {
|
||||
return files[file] ?? files[normalize(file)]
|
||||
}
|
||||
},
|
||||
},
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
|
||||
if (invalidateCache) {
|
||||
|
@ -1088,6 +1088,6 @@ function resolve(
|
|||
props,
|
||||
calls: raw.calls,
|
||||
deps: ctx.deps,
|
||||
raw
|
||||
raw,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
import {
|
||||
type SFCStyleCompileOptions,
|
||||
compileStyle,
|
||||
compileStyleAsync,
|
||||
SFCStyleCompileOptions
|
||||
} from '../src/compileStyle'
|
||||
import path from 'path'
|
||||
import path from 'node:path'
|
||||
|
||||
export function compileScoped(
|
||||
source: string,
|
||||
options?: Partial<SFCStyleCompileOptions>
|
||||
options?: Partial<SFCStyleCompileOptions>,
|
||||
): string {
|
||||
const res = compileStyle({
|
||||
source,
|
||||
filename: 'test.css',
|
||||
id: 'data-v-test',
|
||||
scoped: true,
|
||||
...options
|
||||
...options,
|
||||
})
|
||||
if (res.errors.length) {
|
||||
res.errors.forEach(err => {
|
||||
|
@ -28,34 +28,34 @@ export function compileScoped(
|
|||
describe('SFC scoped CSS', () => {
|
||||
test('simple selectors', () => {
|
||||
expect(compileScoped(`h1 { color: red; }`)).toMatch(
|
||||
`h1[data-v-test] { color: red;`
|
||||
`h1[data-v-test] { color: red;`,
|
||||
)
|
||||
expect(compileScoped(`.foo { color: red; }`)).toMatch(
|
||||
`.foo[data-v-test] { color: red;`
|
||||
`.foo[data-v-test] { color: red;`,
|
||||
)
|
||||
})
|
||||
|
||||
test('descendent selector', () => {
|
||||
expect(compileScoped(`h1 .foo { color: red; }`)).toMatch(
|
||||
`h1 .foo[data-v-test] { color: red;`
|
||||
`h1 .foo[data-v-test] { color: red;`,
|
||||
)
|
||||
})
|
||||
|
||||
test('multiple selectors', () => {
|
||||
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', () => {
|
||||
expect(compileScoped(`.foo:after { color: red; }`)).toMatch(
|
||||
`.foo[data-v-test]:after { color: red;`
|
||||
`.foo[data-v-test]:after { color: red;`,
|
||||
)
|
||||
})
|
||||
|
||||
test('pseudo element', () => {
|
||||
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; }
|
||||
}
|
||||
`,
|
||||
{ id: 'data-v-test' }
|
||||
{ id: 'data-v-test' },
|
||||
)
|
||||
|
||||
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(
|
||||
`.anim-2[data-v-test] {\n animation-name: color-test`
|
||||
`.anim-2[data-v-test] {\n animation-name: color-test`,
|
||||
)
|
||||
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(`@-webkit-keyframes color-test {`)
|
||||
|
||||
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(
|
||||
`.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(
|
||||
`@-webkit-keyframes opacity-test {\nfrom { opacity: 0;`
|
||||
`@-webkit-keyframes opacity-test {\nfrom { opacity: 0;`,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -265,7 +265,7 @@ describe('SFC scoped CSS', () => {
|
|||
}"
|
||||
`)
|
||||
expect(
|
||||
`::v-deep usage as a combinator has been deprecated.`
|
||||
`::v-deep usage as a combinator has been deprecated.`,
|
||||
).toHaveBeenWarned()
|
||||
})
|
||||
|
||||
|
@ -276,7 +276,7 @@ describe('SFC scoped CSS', () => {
|
|||
}"
|
||||
`)
|
||||
expect(
|
||||
`the >>> and /deep/ combinators have been deprecated.`
|
||||
`the >>> and /deep/ combinators have been deprecated.`,
|
||||
).toHaveBeenWarned()
|
||||
})
|
||||
|
||||
|
@ -287,7 +287,7 @@ describe('SFC scoped CSS', () => {
|
|||
}"
|
||||
`)
|
||||
expect(
|
||||
`the >>> and /deep/ combinators have been deprecated.`
|
||||
`the >>> and /deep/ combinators have been deprecated.`,
|
||||
).toHaveBeenWarned()
|
||||
})
|
||||
})
|
||||
|
@ -299,7 +299,7 @@ describe('SFC CSS modules', () => {
|
|||
source: `.red { color: red }\n.green { color: green }\n:global(.blue) { color: blue }`,
|
||||
filename: `test.css`,
|
||||
id: 'test',
|
||||
modules: true
|
||||
modules: true,
|
||||
})
|
||||
expect(result.modules).toBeDefined()
|
||||
expect(result.modules!.red).toMatch('_red_')
|
||||
|
@ -316,8 +316,8 @@ describe('SFC CSS modules', () => {
|
|||
modulesOptions: {
|
||||
scopeBehaviour: 'global',
|
||||
generateScopedName: `[name]__[local]__[hash:base64:5]`,
|
||||
localsConvention: 'camelCaseOnly'
|
||||
}
|
||||
localsConvention: 'camelCaseOnly',
|
||||
},
|
||||
})
|
||||
expect(result.modules).toBeDefined()
|
||||
expect(result.modules!.fooBar).toMatch('__foo-bar__')
|
||||
|
@ -333,11 +333,11 @@ describe('SFC style preprocessors', () => {
|
|||
`,
|
||||
filename: path.resolve(__dirname, './fixture/test.scss'),
|
||||
id: '',
|
||||
preprocessLang: 'scss'
|
||||
preprocessLang: 'scss',
|
||||
})
|
||||
|
||||
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) {
|
||||
width: $size;
|
||||
height: $size;
|
||||
}`
|
||||
}`,
|
||||
},
|
||||
source: `
|
||||
.square {
|
||||
|
@ -357,7 +357,7 @@ describe('SFC style preprocessors', () => {
|
|||
`,
|
||||
filename: path.resolve(__dirname, './fixture/test.scss'),
|
||||
id: '',
|
||||
preprocessLang: 'scss'
|
||||
preprocessLang: 'scss',
|
||||
})
|
||||
|
||||
expect(res.errors.length).toBe(0)
|
||||
|
@ -380,12 +380,12 @@ describe('SFC style preprocessors', () => {
|
|||
width: $size;
|
||||
height: $size;
|
||||
}`
|
||||
}
|
||||
},
|
||||
},
|
||||
source,
|
||||
filename,
|
||||
id: '',
|
||||
preprocessLang: 'scss'
|
||||
preprocessLang: 'scss',
|
||||
})
|
||||
|
||||
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 {
|
||||
type SFCTemplateCompileOptions,
|
||||
compileTemplate,
|
||||
SFCTemplateCompileOptions
|
||||
} from '../src/compileTemplate'
|
||||
import { parse, SFCTemplateBlock } from '../src/parse'
|
||||
import { type SFCTemplateBlock, parse } from '../src/parse'
|
||||
import { compileScript } from '../src'
|
||||
|
||||
function compile(opts: Omit<SFCTemplateCompileOptions, 'id'>) {
|
||||
return compileTemplate({
|
||||
...opts,
|
||||
id: ''
|
||||
id: '',
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -50,13 +50,13 @@ body
|
|||
p Cool Pug example!
|
||||
</template>
|
||||
`,
|
||||
{ filename: 'example.vue', sourceMap: true }
|
||||
{ filename: 'example.vue', sourceMap: true },
|
||||
).descriptor.template as SFCTemplateBlock
|
||||
|
||||
const result = compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
preprocessLang: template.lang
|
||||
preprocessLang: template.lang,
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
|
@ -74,31 +74,31 @@ test('preprocess pug with indents and blank lines', () => {
|
|||
p This is the last line.
|
||||
</template>
|
||||
`,
|
||||
{ filename: 'example.vue', sourceMap: true }
|
||||
{ filename: 'example.vue', sourceMap: true },
|
||||
).descriptor.template as SFCTemplateBlock
|
||||
|
||||
const result = compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
preprocessLang: template.lang
|
||||
preprocessLang: template.lang,
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(0)
|
||||
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', () => {
|
||||
const template = parse(`<template lang="unknownLang">hi</template>\n`, {
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
}).descriptor.template as SFCTemplateBlock
|
||||
|
||||
const result = compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
preprocessLang: template.lang
|
||||
preprocessLang: template.lang,
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(1)
|
||||
|
@ -110,8 +110,8 @@ test('transform asset url options', () => {
|
|||
const { code: code1 } = compile({
|
||||
...input,
|
||||
transformAssetUrls: {
|
||||
tags: { foo: ['bar'] }
|
||||
}
|
||||
tags: { foo: ['bar'] },
|
||||
},
|
||||
})
|
||||
expect(code1).toMatch(`import _imports_0 from 'baz'\n`)
|
||||
|
||||
|
@ -119,15 +119,15 @@ test('transform asset url options', () => {
|
|||
const { code: code2 } = compile({
|
||||
...input,
|
||||
transformAssetUrls: {
|
||||
foo: ['bar']
|
||||
}
|
||||
foo: ['bar'],
|
||||
},
|
||||
})
|
||||
expect(code2).toMatch(`import _imports_0 from 'baz'\n`)
|
||||
|
||||
// false option
|
||||
const { code: code3 } = compile({
|
||||
...input,
|
||||
transformAssetUrls: false
|
||||
transformAssetUrls: false,
|
||||
})
|
||||
expect(code3).not.toMatch(`import _imports_0 from 'baz'\n`)
|
||||
})
|
||||
|
@ -139,12 +139,12 @@ test('source map', () => {
|
|||
<div><p>{{ foobar }}</p></div>
|
||||
</template>
|
||||
`,
|
||||
{ filename: 'example.vue', sourceMap: true }
|
||||
{ filename: 'example.vue', sourceMap: true },
|
||||
).descriptor.template!
|
||||
|
||||
const { code, map } = compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content
|
||||
source: template.content,
|
||||
})
|
||||
|
||||
expect(map!.sources).toEqual([`example.vue`])
|
||||
|
@ -152,7 +152,7 @@ test('source map', () => {
|
|||
|
||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar'))
|
||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar')),
|
||||
).toMatchObject(getPositionInCode(template.content, `foobar`))
|
||||
})
|
||||
|
||||
|
@ -164,7 +164,7 @@ test('should work w/ AST from descriptor', () => {
|
|||
`
|
||||
const template = parse(source, {
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
}).descriptor.template!
|
||||
|
||||
expect(template.ast!.source).toBe(source)
|
||||
|
@ -172,7 +172,7 @@ test('should work w/ AST from descriptor', () => {
|
|||
const { code, map } = compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
ast: template.ast
|
||||
ast: template.ast,
|
||||
})
|
||||
|
||||
expect(map!.sources).toEqual([`example.vue`])
|
||||
|
@ -182,14 +182,14 @@ test('should work w/ AST from descriptor', () => {
|
|||
|
||||
const consumer = new SourceMapConsumer(map as RawSourceMap)
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar'))
|
||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar')),
|
||||
).toMatchObject(getPositionInCode(source, `foobar`))
|
||||
|
||||
expect(code).toBe(
|
||||
compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content
|
||||
}).code
|
||||
source: template.content,
|
||||
}).code,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -201,7 +201,7 @@ test('should work w/ AST from descriptor in SSR mode', () => {
|
|||
`
|
||||
const template = parse(source, {
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
}).descriptor.template!
|
||||
|
||||
expect(template.ast!.source).toBe(source)
|
||||
|
@ -210,7 +210,7 @@ test('should work w/ AST from descriptor in SSR mode', () => {
|
|||
filename: 'example.vue',
|
||||
source: '', // make sure it's actually using the AST instead of source
|
||||
ast: template.ast,
|
||||
ssr: true
|
||||
ssr: true,
|
||||
})
|
||||
|
||||
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)
|
||||
expect(
|
||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar'))
|
||||
consumer.originalPositionFor(getPositionInCode(code, 'foobar')),
|
||||
).toMatchObject(getPositionInCode(source, `foobar`))
|
||||
|
||||
expect(code).toBe(
|
||||
compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
ssr: true
|
||||
}).code
|
||||
ssr: true,
|
||||
}).code,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -240,7 +240,7 @@ test('should not reuse AST if using custom compiler', () => {
|
|||
`
|
||||
const template = parse(source, {
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
}).descriptor.template!
|
||||
|
||||
const { code } = compile({
|
||||
|
@ -249,9 +249,9 @@ test('should not reuse AST if using custom compiler', () => {
|
|||
ast: template.ast,
|
||||
compiler: {
|
||||
parse: () => null as any,
|
||||
// @ts-ignore
|
||||
compile: input => ({ code: input })
|
||||
}
|
||||
// @ts-expect-error
|
||||
compile: input => ({ code: input }),
|
||||
},
|
||||
})
|
||||
|
||||
// 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, {
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
}).descriptor.template!
|
||||
|
||||
// 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({
|
||||
filename: 'example.vue',
|
||||
source: '',
|
||||
ast: template.ast
|
||||
ast: template.ast,
|
||||
})
|
||||
|
||||
expect(code).toBe(
|
||||
compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content
|
||||
}).code
|
||||
source: template.content,
|
||||
}).code,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -296,7 +296,7 @@ test('should force re-parse with correct compiler in SSR mode', () => {
|
|||
`
|
||||
const template = parse(source, {
|
||||
filename: 'example.vue',
|
||||
sourceMap: true
|
||||
sourceMap: true,
|
||||
}).descriptor.template!
|
||||
|
||||
// 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',
|
||||
source: '',
|
||||
ast: template.ast,
|
||||
ssr: true
|
||||
ssr: true,
|
||||
})
|
||||
|
||||
expect(code).toBe(
|
||||
compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
ssr: true
|
||||
}).code
|
||||
ssr: true,
|
||||
}).code,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -323,7 +323,7 @@ test('template errors', () => {
|
|||
const result = compile({
|
||||
filename: 'example.vue',
|
||||
source: `<div
|
||||
:bar="a[" v-model="baz"/>`
|
||||
:bar="a[" v-model="baz"/>`,
|
||||
})
|
||||
expect(result.errors).toMatchSnapshot()
|
||||
})
|
||||
|
@ -335,20 +335,20 @@ test('preprocessor errors', () => {
|
|||
div(class='class)
|
||||
</template>
|
||||
`,
|
||||
{ filename: 'example.vue', sourceMap: true }
|
||||
{ filename: 'example.vue', sourceMap: true },
|
||||
).descriptor.template as SFCTemplateBlock
|
||||
|
||||
const result = compile({
|
||||
filename: 'example.vue',
|
||||
source: template.content,
|
||||
preprocessLang: template.lang
|
||||
preprocessLang: template.lang,
|
||||
})
|
||||
|
||||
expect(result.errors.length).toBe(1)
|
||||
const message = result.errors[0].toString()
|
||||
expect(message).toMatch(`Error: example.vue:3:1`)
|
||||
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"/>
|
||||
</Comp>
|
||||
`,
|
||||
ssr: true
|
||||
ssr: true,
|
||||
})
|
||||
expect(code).toMatch(`_ssrRenderAttr(\"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>
|
||||
</router-link>
|
||||
`,
|
||||
ssr: true
|
||||
ssr: true,
|
||||
})
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -422,7 +422,7 @@ test('prefixing edge case for reused AST', () => {
|
|||
id: 'xxx',
|
||||
filename: 'test.vue',
|
||||
ast: descriptor.template!.ast,
|
||||
source: descriptor.template!.content
|
||||
source: descriptor.template!.content,
|
||||
})
|
||||
expect(code).not.toMatch(`_ctx.t`)
|
||||
})
|
||||
|
@ -436,7 +436,7 @@ interface Pos {
|
|||
function getPositionInCode(
|
||||
code: string,
|
||||
token: string,
|
||||
expectName: string | boolean = false
|
||||
expectName: string | boolean = false,
|
||||
): Pos {
|
||||
const generatedOffset = code.indexOf(token)
|
||||
let line = 1
|
||||
|
@ -452,7 +452,7 @@ function getPositionInCode(
|
|||
column:
|
||||
lastNewLinePos === -1
|
||||
? generatedOffset
|
||||
: generatedOffset - lastNewLinePos - 1
|
||||
: generatedOffset - lastNewLinePos - 1,
|
||||
}
|
||||
if (expectName) {
|
||||
res.name = typeof expectName === 'string' ? expectName : token
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { compileStyle, parse } from '../src'
|
||||
import { mockId, compileSFCScript, assertCode } from './utils'
|
||||
import { assertCode, compileSFCScript, mockId } from './utils'
|
||||
|
||||
describe('CSS vars injection', () => {
|
||||
test('generating correct code for nested paths', () => {
|
||||
|
@ -8,7 +8,7 @@ describe('CSS vars injection', () => {
|
|||
`<style>div{
|
||||
color: v-bind(color);
|
||||
font-size: v-bind('font.size');
|
||||
}</style>`
|
||||
}</style>`,
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||
"${mockId}-color": (_ctx.color),
|
||||
|
@ -32,7 +32,7 @@ describe('CSS vars injection', () => {
|
|||
div {
|
||||
font-size: v-bind(size);
|
||||
}
|
||||
</style>`
|
||||
</style>`,
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||
"${mockId}-size": (_ctx.size)
|
||||
|
@ -57,7 +57,7 @@ describe('CSS vars injection', () => {
|
|||
font-size: v-bind(size);
|
||||
border: v-bind(foo);
|
||||
}
|
||||
</style>`
|
||||
</style>`,
|
||||
)
|
||||
// should handle:
|
||||
// 1. local const bindings
|
||||
|
@ -69,7 +69,7 @@ describe('CSS vars injection', () => {
|
|||
"${mockId}-foo": (__props.foo)
|
||||
})`)
|
||||
expect(content).toMatch(
|
||||
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`
|
||||
`import { useCssVars as _useCssVars, unref as _unref } from 'vue'`,
|
||||
)
|
||||
assertCode(content)
|
||||
})
|
||||
|
@ -85,7 +85,7 @@ describe('CSS vars injection', () => {
|
|||
font-family: v-bind(フォント);
|
||||
}`,
|
||||
filename: 'test.css',
|
||||
id: 'data-v-test'
|
||||
id: 'data-v-test',
|
||||
})
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
".foo {
|
||||
|
@ -106,7 +106,7 @@ describe('CSS vars injection', () => {
|
|||
color: v-bind(color);
|
||||
font-size: v-bind('font.size');
|
||||
}</style>`,
|
||||
{ isProd: true }
|
||||
{ isProd: true },
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||
"4003f1a6": (_ctx.color),
|
||||
|
@ -120,7 +120,7 @@ describe('CSS vars injection', () => {
|
|||
}`,
|
||||
filename: 'test.css',
|
||||
id: mockId,
|
||||
isProd: true
|
||||
isProd: true,
|
||||
})
|
||||
expect(code).toMatchInlineSnapshot(`
|
||||
".foo {
|
||||
|
@ -135,8 +135,8 @@ describe('CSS vars injection', () => {
|
|||
assertCode(
|
||||
compileSFCScript(
|
||||
`<script>const a = 1</script>\n` +
|
||||
`<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
`<style>div{ color: v-bind(color); }</style>`,
|
||||
).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -144,8 +144,8 @@ describe('CSS vars injection', () => {
|
|||
assertCode(
|
||||
compileSFCScript(
|
||||
`<script>export default { setup() {} }</script>\n` +
|
||||
`<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
`<style>div{ color: v-bind(color); }</style>`,
|
||||
).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -155,8 +155,8 @@ describe('CSS vars injection', () => {
|
|||
`<script>
|
||||
// export default {}
|
||||
export default {}
|
||||
</script>\n` + `<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
</script>\n` + `<style>div{ color: v-bind(color); }</style>`,
|
||||
).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -164,8 +164,8 @@ describe('CSS vars injection', () => {
|
|||
assertCode(
|
||||
compileSFCScript(
|
||||
`<script setup>const color = 'red'</script>\n` +
|
||||
`<style>div{ color: v-bind(color); }</style>`
|
||||
).content
|
||||
`<style>div{ color: v-bind(color); }</style>`,
|
||||
).content,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -178,7 +178,7 @@ describe('CSS vars injection', () => {
|
|||
div{ /* color: v-bind(color); */ width:20; }
|
||||
div{ width: v-bind(width); }
|
||||
/* comment */
|
||||
</style>`
|
||||
</style>`,
|
||||
)
|
||||
|
||||
expect(content).not.toMatch(`"${mockId}-color": (color)`)
|
||||
|
@ -198,7 +198,7 @@ describe('CSS vars injection', () => {
|
|||
p {
|
||||
color: v-bind(color);
|
||||
}
|
||||
</style>`
|
||||
</style>`,
|
||||
)
|
||||
// color should only be injected once, even if it is twice in style
|
||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||
|
@ -229,7 +229,7 @@ describe('CSS vars injection', () => {
|
|||
p {
|
||||
color: v-bind(((a + b)) / (2 * a));
|
||||
}
|
||||
</style>`
|
||||
</style>`,
|
||||
)
|
||||
expect(content).toMatch(`_useCssVars(_ctx => ({
|
||||
"${mockId}-foo": (_unref(foo)),
|
||||
|
@ -243,7 +243,7 @@ describe('CSS vars injection', () => {
|
|||
// #6022
|
||||
test('should be able to parse incomplete expressions', () => {
|
||||
const {
|
||||
descriptor: { cssVars }
|
||||
descriptor: { cssVars },
|
||||
} = parse(
|
||||
`<script setup>let xxx = 1</script>
|
||||
<style scoped>
|
||||
|
@ -251,7 +251,7 @@ describe('CSS vars injection', () => {
|
|||
font-weight: v-bind("count.toString(");
|
||||
font-weight: v-bind(xxx);
|
||||
}
|
||||
</style>`
|
||||
</style>`,
|
||||
)
|
||||
expect(cssVars).toMatchObject([`count.toString(`, `xxx`])
|
||||
})
|
||||
|
@ -266,10 +266,10 @@ describe('CSS vars injection', () => {
|
|||
label {
|
||||
background: v-bind(background);
|
||||
}
|
||||
</style>`
|
||||
</style>`,
|
||||
)
|
||||
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,
|
||||
templateOptions: {
|
||||
ssr: true
|
||||
}
|
||||
}
|
||||
ssr: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch(`_useCssVars`)
|
||||
})
|
||||
|
@ -308,9 +308,9 @@ describe('CSS vars injection', () => {
|
|||
{
|
||||
inlineTemplate: false,
|
||||
templateOptions: {
|
||||
ssr: true
|
||||
}
|
||||
}
|
||||
ssr: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch(`_useCssVars`)
|
||||
})
|
||||
|
@ -333,9 +333,9 @@ describe('CSS vars injection', () => {
|
|||
</style>`,
|
||||
{
|
||||
templateOptions: {
|
||||
ssr: true
|
||||
}
|
||||
}
|
||||
ssr: true,
|
||||
},
|
||||
},
|
||||
)
|
||||
expect(content).not.toMatch(`_useCssVars`)
|
||||
})
|
||||
|
|
|
@ -37,7 +37,7 @@ font-weight: bold;
|
|||
}
|
||||
</style>`
|
||||
const {
|
||||
descriptor: { styles }
|
||||
descriptor: { styles },
|
||||
} = parse(src)
|
||||
|
||||
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
|
||||
const padding = Math.round(Math.random() * 10)
|
||||
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
|
||||
|
||||
expect(script!.map).not.toBeUndefined()
|
||||
|
@ -88,7 +88,7 @@ font-weight: bold;
|
|||
h1 foo
|
||||
div bar
|
||||
span baz
|
||||
</template>\n`
|
||||
</template>\n`,
|
||||
).descriptor.template!
|
||||
|
||||
expect(template.map).not.toBeUndefined()
|
||||
|
@ -103,7 +103,7 @@ font-weight: bold;
|
|||
test('custom block', () => {
|
||||
const padding = Math.round(Math.random() * 10)
|
||||
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]
|
||||
|
||||
expect(custom!.map).not.toBeUndefined()
|
||||
|
@ -138,42 +138,42 @@ h1 { color: red }
|
|||
|
||||
const padTrue = parse(content.trim(), { pad: true }).descriptor
|
||||
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(
|
||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n'
|
||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n',
|
||||
)
|
||||
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
|
||||
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(
|
||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n'
|
||||
Array(6 + 1).join('\n') + '\nh1 { color: red }\n',
|
||||
)
|
||||
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
|
||||
expect(padSpace.script!.content).toBe(
|
||||
`<template>\n<div></div>\n</template>\n<script>`.replace(/./g, ' ') +
|
||||
'\nexport default {}\n'
|
||||
'\nexport default {}\n',
|
||||
)
|
||||
expect(padSpace.styles[0].content).toBe(
|
||||
`<template>\n<div></div>\n</template>\n<script>\nexport default {}\n</script>\n<style>`.replace(
|
||||
/./g,
|
||||
' '
|
||||
) + '\nh1 { color: red }\n'
|
||||
' ',
|
||||
) + '\nh1 { color: red }\n',
|
||||
)
|
||||
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(
|
||||
/./g,
|
||||
' '
|
||||
) + '\n{ "greeting": "hello" }\n'
|
||||
' ',
|
||||
) + '\n{ "greeting": "hello" }\n',
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -187,8 +187,8 @@ h1 { color: red }
|
|||
end: {
|
||||
line: 3,
|
||||
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!.loc).toMatchObject({
|
||||
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!.loc).toMatchObject({
|
||||
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(`<custom/>`).descriptor.customBlocks.length).toBe(0)
|
||||
expect(
|
||||
parse(`<custom> \n\t </custom>`).descriptor.customBlocks.length
|
||||
parse(`<custom> \n\t </custom>`).descriptor.customBlocks.length,
|
||||
).toBe(0)
|
||||
})
|
||||
|
||||
|
@ -239,19 +239,19 @@ h1 { color: red }
|
|||
const { descriptor } = parse(
|
||||
`<script></script>\n<script setup>\n</script>`,
|
||||
{
|
||||
ignoreEmpty: false
|
||||
}
|
||||
ignoreEmpty: false,
|
||||
},
|
||||
)
|
||||
expect(descriptor.script).toBeTruthy()
|
||||
expect(descriptor.script!.loc).toMatchObject({
|
||||
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!.loc).toMatchObject({
|
||||
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', () => {
|
||||
const content = `<div><template v-if="ok">ok</template></div>`
|
||||
const { descriptor, errors } = parse(
|
||||
`<template lang="">${content}</template>`
|
||||
`<template lang="">${content}</template>`,
|
||||
)
|
||||
expect(descriptor.template!.content).toBe(content)
|
||||
expect(errors.length).toBe(0)
|
||||
|
@ -277,7 +277,7 @@ h1 { color: red }
|
|||
test('template with preprocessor lang should be treated as plain text', () => {
|
||||
const content = `p(v-if="1 < 2") test <div/>`
|
||||
const { descriptor, errors } = parse(
|
||||
`<template lang="pug">` + content + `</template>`
|
||||
`<template lang="pug">` + content + `</template>`,
|
||||
)
|
||||
expect(errors.length).toBe(0)
|
||||
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><style>h1{color:red;}</style>`).descriptor
|
||||
.slotted
|
||||
.slotted,
|
||||
).toBe(false)
|
||||
expect(
|
||||
parse(
|
||||
`<template>hi</template><style scoped>:slotted(h1){color:red;}</style>`
|
||||
).descriptor.slotted
|
||||
`<template>hi</template><style scoped>:slotted(h1){color:red;}</style>`,
|
||||
).descriptor.slotted,
|
||||
).toBe(true)
|
||||
expect(
|
||||
parse(
|
||||
`<template>hi</template><style scoped>::v-slotted(h1){color:red;}</style>`
|
||||
).descriptor.slotted
|
||||
`<template>hi</template><style scoped>::v-slotted(h1){color:red;}</style>`,
|
||||
).descriptor.slotted,
|
||||
).toBe(true)
|
||||
})
|
||||
|
||||
|
@ -332,8 +332,8 @@ h1 { color: red }
|
|||
options.onError!(new Error('foo') as any)
|
||||
return createRoot([])
|
||||
},
|
||||
compile: baseCompile
|
||||
}
|
||||
compile: baseCompile,
|
||||
},
|
||||
})
|
||||
expect(errors.length).toBe(2)
|
||||
// error thrown by the custom parse
|
||||
|
@ -344,7 +344,7 @@ h1 { color: red }
|
|||
|
||||
test('treat custom blocks as raw text', () => {
|
||||
const { errors, descriptor } = parse(
|
||||
`<template><input></template><foo> <-& </foo>`
|
||||
`<template><input></template><foo> <-& </foo>`,
|
||||
)
|
||||
expect(errors.length).toBe(0)
|
||||
expect(descriptor.customBlocks[0].content).toBe(` <-& `)
|
||||
|
@ -358,7 +358,7 @@ h1 { color: red }
|
|||
test('should only allow single template element', () => {
|
||||
assertWarning(
|
||||
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(
|
||||
parse(`<script>console.log(1)</script><script>console.log(1)</script>`)
|
||||
.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', () => {
|
||||
assertWarning(
|
||||
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,
|
||||
`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', () => {
|
||||
expect(
|
||||
parse(
|
||||
`<script setup>console.log(1)</script><script>console.log(1)</script>`
|
||||
).errors.length
|
||||
`<script setup>console.log(1)</script><script>console.log(1)</script>`,
|
||||
).errors.length,
|
||||
).toBe(0)
|
||||
})
|
||||
|
||||
|
@ -391,7 +391,7 @@ h1 { color: red }
|
|||
test('should throw error if no <template> or <script> is present', () => {
|
||||
assertWarning(
|
||||
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', () => {
|
||||
expect(
|
||||
rewriteDefault(`export default {}`, 'script')
|
||||
rewriteDefault(`export default {}`, 'script'),
|
||||
).toMatchInlineSnapshot(`"const script = {}"`)
|
||||
})
|
||||
|
||||
|
@ -27,8 +27,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \n export { a as b, a as default, a as c}`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export { a as b, a as c}
|
||||
|
@ -38,8 +38,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \n export { a as b, a as default , a as c}`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export { a as b, a as c}
|
||||
|
@ -49,8 +49,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \n export { a as b } \n export { a as default, a as c }`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export { a as b }
|
||||
|
@ -69,7 +69,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
|
||||
test('export named default multiline', () => {
|
||||
expect(
|
||||
rewriteDefault(`let App = {}\n export {\nApp as default\n}`, '_sfc_main')
|
||||
rewriteDefault(`let App = {}\n export {\nApp as default\n}`, '_sfc_main'),
|
||||
).toMatchInlineSnapshot(`
|
||||
"let App = {}
|
||||
export {
|
||||
|
@ -84,8 +84,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
rewriteDefault(
|
||||
`const a = 1 \n export {\n a as b,\n a as default,\n a as c}\n` +
|
||||
`// export { myFunction as default }`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export {
|
||||
|
@ -100,8 +100,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
rewriteDefault(
|
||||
`const a = 1 \n export {\n a as b,\n a as default ,\n a as c}\n` +
|
||||
`// export { myFunction as default }`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"const a = 1
|
||||
export {
|
||||
|
@ -115,7 +115,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
|
||||
test(`export { default } from '...'`, async () => {
|
||||
expect(
|
||||
rewriteDefault(`export { default, foo } from './index.js'`, 'script')
|
||||
rewriteDefault(`export { default, foo } from './index.js'`, 'script'),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||
export { foo } from './index.js'
|
||||
|
@ -123,7 +123,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(`export { default , foo } from './index.js'`, 'script')
|
||||
rewriteDefault(`export { default , foo } from './index.js'`, 'script'),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||
export { foo } from './index.js'
|
||||
|
@ -131,7 +131,7 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
`)
|
||||
|
||||
expect(
|
||||
rewriteDefault(`export { foo, default } from './index.js'`, 'script')
|
||||
rewriteDefault(`export { foo, default } from './index.js'`, 'script'),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { default as __VUE_DEFAULT__ } from './index.js'
|
||||
export { foo, } from './index.js'
|
||||
|
@ -141,8 +141,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`export { foo as default, bar } from './index.js'`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||
export { bar } from './index.js'
|
||||
|
@ -152,8 +152,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`export { foo as default , bar } from './index.js'`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||
export { bar } from './index.js'
|
||||
|
@ -163,8 +163,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`export { bar, foo as default } from './index.js'`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||
export { bar, } from './index.js'
|
||||
|
@ -174,8 +174,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`export { foo as default } from './index.js' \n const foo = 1`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { foo as __VUE_DEFAULT__ } from './index.js'
|
||||
export { } from './index.js'
|
||||
|
@ -186,8 +186,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`const a = 1 \nexport { a as default } from 'xxx'`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"import { a as __VUE_DEFAULT__ } from 'xxx'
|
||||
const a = 1
|
||||
|
@ -206,7 +206,10 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
|
||||
test('export default class w/ comments', async () => {
|
||||
expect(
|
||||
rewriteDefault(`// export default\nexport default class Foo {}`, 'script')
|
||||
rewriteDefault(
|
||||
`// export default\nexport default class Foo {}`,
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"// export default
|
||||
class Foo {}
|
||||
|
@ -218,8 +221,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`export default {}\n` + `// export default class Foo {}`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"const script = {}
|
||||
// export default class Foo {}"
|
||||
|
@ -230,8 +233,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`/*\nexport default class Foo {}*/\n` + `export default class Bar {}`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"/*
|
||||
export default class Foo {}*/
|
||||
|
@ -243,8 +246,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
test('@Component\nexport default class', async () => {
|
||||
expect(
|
||||
rewriteDefault(`@Component\nexport default class Foo {}`, 'script', [
|
||||
'decorators-legacy'
|
||||
])
|
||||
'decorators-legacy',
|
||||
]),
|
||||
).toMatchInlineSnapshot(`
|
||||
"@Component class Foo {}
|
||||
const script = Foo"
|
||||
|
@ -256,8 +259,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
rewriteDefault(
|
||||
`// export default\n@Component\nexport default class Foo {}`,
|
||||
'script',
|
||||
['decorators-legacy']
|
||||
)
|
||||
['decorators-legacy'],
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"// export default
|
||||
@Component class Foo {}
|
||||
|
@ -269,8 +272,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
expect(
|
||||
rewriteDefault(
|
||||
`export default {}\n` + `// @Component\n// export default class Foo {}`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"const script = {}
|
||||
// @Component
|
||||
|
@ -283,8 +286,8 @@ describe('compiler sfc: rewriteDefault', () => {
|
|||
rewriteDefault(
|
||||
`/*\n@Component\nexport default class Foo {}*/\n` +
|
||||
`export default class Bar {}`,
|
||||
'script'
|
||||
)
|
||||
'script',
|
||||
),
|
||||
).toMatchInlineSnapshot(`
|
||||
"/*
|
||||
@Component
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {
|
||||
generate,
|
||||
type TransformOptions,
|
||||
baseParse,
|
||||
generate,
|
||||
transform,
|
||||
TransformOptions
|
||||
} from '@vue/compiler-core'
|
||||
import {
|
||||
transformAssetUrl,
|
||||
type AssetURLOptions,
|
||||
createAssetUrlTransformWithOptions,
|
||||
AssetURLOptions,
|
||||
normalizeOptions
|
||||
normalizeOptions,
|
||||
transformAssetUrl,
|
||||
} from '../src/template/transformAssetUrl'
|
||||
import { transformElement } from '../../compiler-core/src/transforms/transformElement'
|
||||
import { transformBind } from '../../compiler-core/src/transforms/vBind'
|
||||
|
@ -17,7 +17,7 @@ import { stringifyStatic } from '../../compiler-dom/src/transforms/stringifyStat
|
|||
function compileWithAssetUrls(
|
||||
template: string,
|
||||
options?: AssetURLOptions,
|
||||
transformOptions?: TransformOptions
|
||||
transformOptions?: TransformOptions,
|
||||
) {
|
||||
const ast = baseParse(template)
|
||||
const t = options
|
||||
|
@ -26,9 +26,9 @@ function compileWithAssetUrls(
|
|||
transform(ast, {
|
||||
nodeTransforms: [t, transformElement],
|
||||
directiveTransforms: {
|
||||
bind: transformBind
|
||||
bind: transformBind,
|
||||
},
|
||||
...transformOptions
|
||||
...transformOptions,
|
||||
})
|
||||
return generate(ast, { mode: 'module' })
|
||||
}
|
||||
|
@ -57,8 +57,8 @@ describe('compiler sfc: transform asset url', () => {
|
|||
'<use href="~@svg/file.svg#fragment"></use>',
|
||||
{},
|
||||
{
|
||||
hoistStatic: true
|
||||
}
|
||||
hoistStatic: true,
|
||||
},
|
||||
)
|
||||
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="@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_1 from '@theme/bar.png'`)
|
||||
|
@ -94,8 +94,8 @@ describe('compiler sfc: transform asset url', () => {
|
|||
`<img src="https://foo.bar/baz.png"/>` +
|
||||
`<img src="//foo.bar/baz.png"/>`,
|
||||
{
|
||||
includeAbsolute: true
|
||||
}
|
||||
includeAbsolute: true,
|
||||
},
|
||||
)
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
@ -108,7 +108,7 @@ describe('compiler sfc: transform asset url', () => {
|
|||
<circle id="myCircle" cx="0" cy="0" r="5" />
|
||||
</defs>
|
||||
<use x="5" y="5" xlink:href="#myCircle" />
|
||||
</svg>`
|
||||
</svg>`,
|
||||
)
|
||||
// should not remove it
|
||||
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', () => {
|
||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||
base: 'http://localhost:3000/src/'
|
||||
base: 'http://localhost:3000/src/',
|
||||
})
|
||||
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -124,7 +124,7 @@ describe('compiler sfc: transform asset url', () => {
|
|||
|
||||
test('should allow for full base URLs, without paths', () => {
|
||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||
base: 'http://localhost:3000'
|
||||
base: 'http://localhost:3000',
|
||||
})
|
||||
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -132,7 +132,7 @@ describe('compiler sfc: transform asset url', () => {
|
|||
|
||||
test('should allow for full base URLs, without port', () => {
|
||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||
base: 'http://localhost'
|
||||
base: 'http://localhost',
|
||||
})
|
||||
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -140,7 +140,7 @@ describe('compiler sfc: transform asset url', () => {
|
|||
|
||||
test('should allow for full base URLs, without protocol', () => {
|
||||
const { code } = compileWithAssetUrls(`<img src="./logo.png" />`, {
|
||||
base: '//localhost'
|
||||
base: '//localhost',
|
||||
})
|
||||
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -156,12 +156,12 @@ describe('compiler sfc: transform asset url', () => {
|
|||
`<img src="./bar.png"/>` +
|
||||
`</div>`,
|
||||
{
|
||||
includeAbsolute: true
|
||||
includeAbsolute: true,
|
||||
},
|
||||
{
|
||||
hoistStatic: true,
|
||||
transformHoist: stringifyStatic
|
||||
}
|
||||
transformHoist: stringifyStatic,
|
||||
},
|
||||
)
|
||||
expect(code).toMatch(`_createStaticVNode`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -171,12 +171,12 @@ describe('compiler sfc: transform asset url', () => {
|
|||
const { code } = compileWithAssetUrls(
|
||||
`<div><img src="/foo bar.png"/></div>`,
|
||||
{
|
||||
includeAbsolute: true
|
||||
includeAbsolute: true,
|
||||
},
|
||||
{
|
||||
hoistStatic: true,
|
||||
transformHoist: stringifyStatic
|
||||
}
|
||||
transformHoist: stringifyStatic,
|
||||
},
|
||||
)
|
||||
expect(code).toMatch(`_createElementVNode`)
|
||||
expect(code).toContain(`import _imports_0 from '/foo bar.png'`)
|
||||
|
@ -186,12 +186,12 @@ describe('compiler sfc: transform asset url', () => {
|
|||
const { code } = compileWithAssetUrls(
|
||||
`<div><img src="./foo bar.png"/></div>`,
|
||||
{
|
||||
includeAbsolute: true
|
||||
includeAbsolute: true,
|
||||
},
|
||||
{
|
||||
hoistStatic: true,
|
||||
transformHoist: stringifyStatic
|
||||
}
|
||||
transformHoist: stringifyStatic,
|
||||
},
|
||||
)
|
||||
expect(code).toMatch(`_createElementVNode`)
|
||||
expect(code).toContain(`import _imports_0 from './foo bar.png'`)
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
import {
|
||||
generate,
|
||||
type TransformOptions,
|
||||
baseParse,
|
||||
generate,
|
||||
transform,
|
||||
TransformOptions
|
||||
} from '@vue/compiler-core'
|
||||
import {
|
||||
createSrcsetTransformWithOptions,
|
||||
transformSrcset,
|
||||
createSrcsetTransformWithOptions
|
||||
} from '../src/template/transformSrcset'
|
||||
import { transformElement } from '../../compiler-core/src/transforms/transformElement'
|
||||
import { transformBind } from '../../compiler-core/src/transforms/vBind'
|
||||
import {
|
||||
AssetURLOptions,
|
||||
normalizeOptions
|
||||
type AssetURLOptions,
|
||||
normalizeOptions,
|
||||
} from '../src/template/transformAssetUrl'
|
||||
import { stringifyStatic } from '../../compiler-dom/src/transforms/stringifyStatic'
|
||||
|
||||
function compileWithSrcset(
|
||||
template: string,
|
||||
options?: AssetURLOptions,
|
||||
transformOptions?: TransformOptions
|
||||
transformOptions?: TransformOptions,
|
||||
) {
|
||||
const ast = baseParse(template)
|
||||
const srcsetTransform = options
|
||||
|
@ -29,9 +29,9 @@ function compileWithSrcset(
|
|||
hoistStatic: true,
|
||||
nodeTransforms: [srcsetTransform, transformElement],
|
||||
directiveTransforms: {
|
||||
bind: transformBind
|
||||
bind: transformBind,
|
||||
},
|
||||
...transformOptions
|
||||
...transformOptions,
|
||||
})
|
||||
return generate(ast, { mode: 'module' })
|
||||
}
|
||||
|
@ -59,16 +59,16 @@ describe('compiler sfc: transform srcset', () => {
|
|||
test('transform srcset w/ base', () => {
|
||||
expect(
|
||||
compileWithSrcset(src, {
|
||||
base: '/foo'
|
||||
}).code
|
||||
base: '/foo',
|
||||
}).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('transform srcset w/ includeAbsolute: true', () => {
|
||||
expect(
|
||||
compileWithSrcset(src, {
|
||||
includeAbsolute: true
|
||||
}).code
|
||||
includeAbsolute: true,
|
||||
}).code,
|
||||
).toMatchSnapshot()
|
||||
})
|
||||
|
||||
|
@ -76,12 +76,12 @@ describe('compiler sfc: transform srcset', () => {
|
|||
const code = compileWithSrcset(
|
||||
`<div>${src}</div>`,
|
||||
{
|
||||
includeAbsolute: true
|
||||
includeAbsolute: true,
|
||||
},
|
||||
{
|
||||
hoistStatic: true,
|
||||
transformHoist: stringifyStatic
|
||||
}
|
||||
transformHoist: stringifyStatic,
|
||||
},
|
||||
).code
|
||||
expect(code).toMatch(`_createStaticVNode`)
|
||||
expect(code).toMatchSnapshot()
|
||||
|
@ -94,7 +94,7 @@ describe('compiler sfc: transform srcset', () => {
|
|||
<img srcset="@/logo.png 1x, ./logo.png 2x"/>
|
||||
`,
|
||||
{ base: '/foo/' },
|
||||
{ hoistStatic: true }
|
||||
{ hoistStatic: true },
|
||||
).code
|
||||
expect(code).toMatchSnapshot()
|
||||
})
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {
|
||||
isRelativeUrl,
|
||||
isDataUrl,
|
||||
isExternalUrl,
|
||||
isDataUrl
|
||||
isRelativeUrl,
|
||||
} from '../src/template/templateUtils'
|
||||
|
||||
describe('compiler sfc:templateUtils isRelativeUrl', () => {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {
|
||||
parse,
|
||||
SFCScriptCompileOptions,
|
||||
type SFCParseOptions,
|
||||
type SFCScriptCompileOptions,
|
||||
compileScript,
|
||||
SFCParseOptions
|
||||
parse,
|
||||
} from '../src'
|
||||
import { parse as babelParse } from '@babel/parser'
|
||||
|
||||
|
@ -11,7 +11,7 @@ export const mockId = 'xxxxxxxx'
|
|||
export function compileSFCScript(
|
||||
src: string,
|
||||
options?: Partial<SFCScriptCompileOptions>,
|
||||
parseOptions?: SFCParseOptions
|
||||
parseOptions?: SFCParseOptions,
|
||||
) {
|
||||
const { descriptor, errors } = parse(src, parseOptions)
|
||||
if (errors.length) {
|
||||
|
@ -19,7 +19,7 @@ export function compileSFCScript(
|
|||
}
|
||||
return compileScript(descriptor, {
|
||||
...options,
|
||||
id: mockId
|
||||
id: mockId,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -30,8 +30,8 @@ export function assertCode(code: string) {
|
|||
sourceType: 'module',
|
||||
plugins: [
|
||||
'typescript',
|
||||
['importAttributes', { deprecatedAssertSyntax: true }]
|
||||
]
|
||||
['importAttributes', { deprecatedAssertSyntax: true }],
|
||||
],
|
||||
})
|
||||
} catch (e: any) {
|
||||
console.log(code)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { LRUCache } from 'lru-cache'
|
||||
|
||||
export function createCache<T extends {}>(
|
||||
max = 500
|
||||
max = 500,
|
||||
): Map<string, T> | LRUCache<string, T> {
|
||||
if (__GLOBAL__ || __ESM_BROWSER__) {
|
||||
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