wip: filters compat
This commit is contained in:
parent
467076361a
commit
7dc681c196
@ -109,6 +109,9 @@ export interface RootNode extends Node {
|
|||||||
temps: number
|
temps: number
|
||||||
ssrHelpers?: symbol[]
|
ssrHelpers?: symbol[]
|
||||||
codegenNode?: TemplateChildNode | JSChildNode | BlockStatement
|
codegenNode?: TemplateChildNode | JSChildNode | BlockStatement
|
||||||
|
|
||||||
|
// v2 compat only
|
||||||
|
filters?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ElementNode =
|
export type ElementNode =
|
||||||
|
@ -50,7 +50,8 @@ import {
|
|||||||
CREATE_BLOCK,
|
CREATE_BLOCK,
|
||||||
OPEN_BLOCK,
|
OPEN_BLOCK,
|
||||||
CREATE_STATIC,
|
CREATE_STATIC,
|
||||||
WITH_CTX
|
WITH_CTX,
|
||||||
|
RESOLVE_FILTER
|
||||||
} from './runtimeHelpers'
|
} from './runtimeHelpers'
|
||||||
import { ImportItem } from './transform'
|
import { ImportItem } from './transform'
|
||||||
|
|
||||||
@ -274,6 +275,12 @@ export function generate(
|
|||||||
newline()
|
newline()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (__COMPAT__ && ast.filters && ast.filters.length) {
|
||||||
|
newline()
|
||||||
|
genAssets(ast.filters, 'filter', context)
|
||||||
|
newline()
|
||||||
|
}
|
||||||
|
|
||||||
if (ast.temps > 0) {
|
if (ast.temps > 0) {
|
||||||
push(`let `)
|
push(`let `)
|
||||||
for (let i = 0; i < ast.temps; i++) {
|
for (let i = 0; i < ast.temps; i++) {
|
||||||
@ -458,11 +465,15 @@ function genModulePreamble(
|
|||||||
|
|
||||||
function genAssets(
|
function genAssets(
|
||||||
assets: string[],
|
assets: string[],
|
||||||
type: 'component' | 'directive',
|
type: 'component' | 'directive' | 'filter',
|
||||||
{ helper, push, newline }: CodegenContext
|
{ helper, push, newline }: CodegenContext
|
||||||
) {
|
) {
|
||||||
const resolver = helper(
|
const resolver = helper(
|
||||||
type === 'component' ? RESOLVE_COMPONENT : RESOLVE_DIRECTIVE
|
__COMPAT__ && type === 'filter'
|
||||||
|
? RESOLVE_FILTER
|
||||||
|
: type === 'component'
|
||||||
|
? RESOLVE_COMPONENT
|
||||||
|
: RESOLVE_DIRECTIVE
|
||||||
)
|
)
|
||||||
for (let i = 0; i < assets.length; i++) {
|
for (let i = 0; i < assets.length; i++) {
|
||||||
let id = assets[i]
|
let id = assets[i]
|
||||||
|
@ -22,7 +22,7 @@ export const enum CompilerDeprecationTypes {
|
|||||||
COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',
|
COMPILER_V_IF_V_FOR_PRECEDENCE = 'COMPILER_V_IF_V_FOR_PRECEDENCE',
|
||||||
COMPILER_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',
|
COMPILER_NATIVE_TEMPLATE = 'COMPILER_NATIVE_TEMPLATE',
|
||||||
COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',
|
COMPILER_INLINE_TEMPLATE = 'COMPILER_INLINE_TEMPLATE',
|
||||||
COMPILER_FILTER = 'COMPILER_FILTER'
|
COMPILER_FILTERS = 'COMPILER_FILTER'
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeprecationData = {
|
type DeprecationData = {
|
||||||
@ -89,8 +89,11 @@ const deprecationData: Record<CompilerDeprecationTypes, DeprecationData> = {
|
|||||||
link: `https://v3.vuejs.org/guide/migration/inline-template-attribute.html`
|
link: `https://v3.vuejs.org/guide/migration/inline-template-attribute.html`
|
||||||
},
|
},
|
||||||
|
|
||||||
[CompilerDeprecationTypes.COMPILER_FILTER]: {
|
[CompilerDeprecationTypes.COMPILER_FILTERS]: {
|
||||||
message: `filters have been removed in Vue 3.`,
|
message:
|
||||||
|
`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.vuejs.org/guide/migration/filters.html`
|
link: `https://v3.vuejs.org/guide/migration/filters.html`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
194
packages/compiler-core/src/compat/transformFilter.ts
Normal file
194
packages/compiler-core/src/compat/transformFilter.ts
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
import { RESOLVE_FILTER } from '../runtimeHelpers'
|
||||||
|
import {
|
||||||
|
AttributeNode,
|
||||||
|
DirectiveNode,
|
||||||
|
NodeTransform,
|
||||||
|
NodeTypes,
|
||||||
|
SimpleExpressionNode,
|
||||||
|
toValidAssetId,
|
||||||
|
TransformContext
|
||||||
|
} from '@vue/compiler-core'
|
||||||
|
import {
|
||||||
|
CompilerDeprecationTypes,
|
||||||
|
isCompatEnabled,
|
||||||
|
warnDeprecation
|
||||||
|
} from './compatConfig'
|
||||||
|
import { ExpressionNode } from '../ast'
|
||||||
|
|
||||||
|
const validDivisionCharRE = /[\w).+\-_$\]]/
|
||||||
|
|
||||||
|
export const transformFilter: NodeTransform = (node, context) => {
|
||||||
|
if (!isCompatEnabled(CompilerDeprecationTypes.COMPILER_FILTERS, context)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.type === NodeTypes.INTERPOLATION) {
|
||||||
|
// filter rewrite is applied before expression transform so only
|
||||||
|
// simple expressions are possible at this stage
|
||||||
|
rewriteFilter(node.content, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.type === NodeTypes.ELEMENT) {
|
||||||
|
node.props.forEach((prop: AttributeNode | DirectiveNode) => {
|
||||||
|
if (
|
||||||
|
prop.type === NodeTypes.DIRECTIVE &&
|
||||||
|
prop.name !== 'for' &&
|
||||||
|
prop.exp
|
||||||
|
) {
|
||||||
|
rewriteFilter(prop.exp, context)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function rewriteFilter(node: ExpressionNode, context: TransformContext) {
|
||||||
|
if (node.type === NodeTypes.SIMPLE_EXPRESSION) {
|
||||||
|
parseFilter(node, context)
|
||||||
|
} else {
|
||||||
|
for (let i = 0; i < node.children.length; i++) {
|
||||||
|
const child = node.children[i]
|
||||||
|
if (typeof child !== 'object') continue
|
||||||
|
if (child.type === NodeTypes.SIMPLE_EXPRESSION) {
|
||||||
|
parseFilter(child, context)
|
||||||
|
} else if (child.type === NodeTypes.COMPOUND_EXPRESSION) {
|
||||||
|
rewriteFilter(node, context)
|
||||||
|
} else if (child.type === NodeTypes.INTERPOLATION) {
|
||||||
|
rewriteFilter(child.content, context)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseFilter(node: SimpleExpressionNode, context: TransformContext) {
|
||||||
|
const exp = node.content
|
||||||
|
let inSingle = false
|
||||||
|
let inDouble = false
|
||||||
|
let inTemplateString = false
|
||||||
|
let inRegex = false
|
||||||
|
let curly = 0
|
||||||
|
let square = 0
|
||||||
|
let paren = 0
|
||||||
|
let lastFilterIndex = 0
|
||||||
|
let c,
|
||||||
|
prev,
|
||||||
|
i: number,
|
||||||
|
expression,
|
||||||
|
filters: string[] = []
|
||||||
|
|
||||||
|
for (i = 0; i < exp.length; i++) {
|
||||||
|
prev = c
|
||||||
|
c = exp.charCodeAt(i)
|
||||||
|
if (inSingle) {
|
||||||
|
if (c === 0x27 && prev !== 0x5c) inSingle = false
|
||||||
|
} else if (inDouble) {
|
||||||
|
if (c === 0x22 && prev !== 0x5c) inDouble = false
|
||||||
|
} else if (inTemplateString) {
|
||||||
|
if (c === 0x60 && prev !== 0x5c) inTemplateString = false
|
||||||
|
} else if (inRegex) {
|
||||||
|
if (c === 0x2f && prev !== 0x5c) inRegex = false
|
||||||
|
} else if (
|
||||||
|
c === 0x7c && // pipe
|
||||||
|
exp.charCodeAt(i + 1) !== 0x7c &&
|
||||||
|
exp.charCodeAt(i - 1) !== 0x7c &&
|
||||||
|
!curly &&
|
||||||
|
!square &&
|
||||||
|
!paren
|
||||||
|
) {
|
||||||
|
if (expression === undefined) {
|
||||||
|
// first filter, end of expression
|
||||||
|
lastFilterIndex = i + 1
|
||||||
|
expression = exp.slice(0, i).trim()
|
||||||
|
} else {
|
||||||
|
pushFilter()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
switch (c) {
|
||||||
|
case 0x22:
|
||||||
|
inDouble = true
|
||||||
|
break // "
|
||||||
|
case 0x27:
|
||||||
|
inSingle = true
|
||||||
|
break // '
|
||||||
|
case 0x60:
|
||||||
|
inTemplateString = true
|
||||||
|
break // `
|
||||||
|
case 0x28:
|
||||||
|
paren++
|
||||||
|
break // (
|
||||||
|
case 0x29:
|
||||||
|
paren--
|
||||||
|
break // )
|
||||||
|
case 0x5b:
|
||||||
|
square++
|
||||||
|
break // [
|
||||||
|
case 0x5d:
|
||||||
|
square--
|
||||||
|
break // ]
|
||||||
|
case 0x7b:
|
||||||
|
curly++
|
||||||
|
break // {
|
||||||
|
case 0x7d:
|
||||||
|
curly--
|
||||||
|
break // }
|
||||||
|
}
|
||||||
|
if (c === 0x2f) {
|
||||||
|
// /
|
||||||
|
let j = i - 1
|
||||||
|
let p
|
||||||
|
// find first non-whitespace prev char
|
||||||
|
for (; j >= 0; j--) {
|
||||||
|
p = exp.charAt(j)
|
||||||
|
if (p !== ' ') break
|
||||||
|
}
|
||||||
|
if (!p || !validDivisionCharRE.test(p)) {
|
||||||
|
inRegex = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expression === undefined) {
|
||||||
|
expression = exp.slice(0, i).trim()
|
||||||
|
} else if (lastFilterIndex !== 0) {
|
||||||
|
pushFilter()
|
||||||
|
}
|
||||||
|
|
||||||
|
function pushFilter() {
|
||||||
|
filters.push(exp.slice(lastFilterIndex, i).trim())
|
||||||
|
lastFilterIndex = i + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
filters.length &&
|
||||||
|
warnDeprecation(
|
||||||
|
CompilerDeprecationTypes.COMPILER_FILTERS,
|
||||||
|
context,
|
||||||
|
node.loc
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
for (i = 0; i < filters.length; i++) {
|
||||||
|
expression = wrapFilter(expression, filters[i], context)
|
||||||
|
}
|
||||||
|
node.content = expression
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function wrapFilter(
|
||||||
|
exp: string,
|
||||||
|
filter: string,
|
||||||
|
context: TransformContext
|
||||||
|
): string {
|
||||||
|
context.helper(RESOLVE_FILTER)
|
||||||
|
const i = filter.indexOf('(')
|
||||||
|
if (i < 0) {
|
||||||
|
context.filters!.add(filter)
|
||||||
|
return `${toValidAssetId(filter, 'filter')}(${exp})`
|
||||||
|
} else {
|
||||||
|
const name = filter.slice(0, i)
|
||||||
|
const args = filter.slice(i + 1)
|
||||||
|
context.filters!.add(name)
|
||||||
|
return `${toValidAssetId(name, 'filter')}(${exp}${
|
||||||
|
args !== ')' ? ',' + args : args
|
||||||
|
}`
|
||||||
|
}
|
||||||
|
}
|
@ -15,6 +15,7 @@ import { trackSlotScopes, trackVForSlotScopes } from './transforms/vSlot'
|
|||||||
import { transformText } from './transforms/transformText'
|
import { transformText } from './transforms/transformText'
|
||||||
import { transformOnce } from './transforms/vOnce'
|
import { transformOnce } from './transforms/vOnce'
|
||||||
import { transformModel } from './transforms/vModel'
|
import { transformModel } from './transforms/vModel'
|
||||||
|
import { transformFilter } from './compat/transformFilter'
|
||||||
import { defaultOnError, createCompilerError, ErrorCodes } from './errors'
|
import { defaultOnError, createCompilerError, ErrorCodes } from './errors'
|
||||||
|
|
||||||
export type TransformPreset = [
|
export type TransformPreset = [
|
||||||
@ -30,6 +31,7 @@ export function getBaseTransformPreset(
|
|||||||
transformOnce,
|
transformOnce,
|
||||||
transformIf,
|
transformIf,
|
||||||
transformFor,
|
transformFor,
|
||||||
|
...(__COMPAT__ ? [transformFilter] : []),
|
||||||
...(!__BROWSER__ && prefixIdentifiers
|
...(!__BROWSER__ && prefixIdentifiers
|
||||||
? [
|
? [
|
||||||
// order is important
|
// order is important
|
||||||
|
@ -14,6 +14,7 @@ export const RESOLVE_DYNAMIC_COMPONENT = Symbol(
|
|||||||
__DEV__ ? `resolveDynamicComponent` : ``
|
__DEV__ ? `resolveDynamicComponent` : ``
|
||||||
)
|
)
|
||||||
export const RESOLVE_DIRECTIVE = Symbol(__DEV__ ? `resolveDirective` : ``)
|
export const RESOLVE_DIRECTIVE = Symbol(__DEV__ ? `resolveDirective` : ``)
|
||||||
|
export const RESOLVE_FILTER = Symbol(__DEV__ ? `resolveFilter` : ``)
|
||||||
export const WITH_DIRECTIVES = Symbol(__DEV__ ? `withDirectives` : ``)
|
export const WITH_DIRECTIVES = Symbol(__DEV__ ? `withDirectives` : ``)
|
||||||
export const RENDER_LIST = Symbol(__DEV__ ? `renderList` : ``)
|
export const RENDER_LIST = Symbol(__DEV__ ? `renderList` : ``)
|
||||||
export const RENDER_SLOT = Symbol(__DEV__ ? `renderSlot` : ``)
|
export const RENDER_SLOT = Symbol(__DEV__ ? `renderSlot` : ``)
|
||||||
@ -50,6 +51,7 @@ export const helperNameMap: any = {
|
|||||||
[RESOLVE_COMPONENT]: `resolveComponent`,
|
[RESOLVE_COMPONENT]: `resolveComponent`,
|
||||||
[RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`,
|
[RESOLVE_DYNAMIC_COMPONENT]: `resolveDynamicComponent`,
|
||||||
[RESOLVE_DIRECTIVE]: `resolveDirective`,
|
[RESOLVE_DIRECTIVE]: `resolveDirective`,
|
||||||
|
[RESOLVE_FILTER]: `resolveFilter`,
|
||||||
[WITH_DIRECTIVES]: `withDirectives`,
|
[WITH_DIRECTIVES]: `withDirectives`,
|
||||||
[RENDER_LIST]: `renderList`,
|
[RENDER_LIST]: `renderList`,
|
||||||
[RENDER_SLOT]: `renderSlot`,
|
[RENDER_SLOT]: `renderSlot`,
|
||||||
|
@ -118,6 +118,9 @@ export interface TransformContext
|
|||||||
hoist(exp: JSChildNode): SimpleExpressionNode
|
hoist(exp: JSChildNode): SimpleExpressionNode
|
||||||
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
|
cache<T extends JSChildNode>(exp: T, isVNode?: boolean): CacheExpression | T
|
||||||
constantCache: Map<TemplateChildNode, ConstantTypes>
|
constantCache: Map<TemplateChildNode, ConstantTypes>
|
||||||
|
|
||||||
|
// 2.x Compat only
|
||||||
|
filters?: Set<string>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTransformContext(
|
export function createTransformContext(
|
||||||
@ -289,6 +292,10 @@ export function createTransformContext(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (__COMPAT__) {
|
||||||
|
context.filters = new Set()
|
||||||
|
}
|
||||||
|
|
||||||
function addId(id: string) {
|
function addId(id: string) {
|
||||||
const { identifiers } = context
|
const { identifiers } = context
|
||||||
if (identifiers[id] === undefined) {
|
if (identifiers[id] === undefined) {
|
||||||
@ -321,6 +328,10 @@ export function transform(root: RootNode, options: TransformOptions) {
|
|||||||
root.hoists = context.hoists
|
root.hoists = context.hoists
|
||||||
root.temps = context.temps
|
root.temps = context.temps
|
||||||
root.cached = context.cached
|
root.cached = context.cached
|
||||||
|
|
||||||
|
if (__COMPAT__) {
|
||||||
|
root.filters = [...context.filters!]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createRootCodegen(root: RootNode, context: TransformContext) {
|
function createRootCodegen(root: RootNode, context: TransformContext) {
|
||||||
|
@ -254,6 +254,11 @@ export function processExpression(
|
|||||||
parent && parentStack.push(parent)
|
parent && parentStack.push(parent)
|
||||||
if (node.type === 'Identifier') {
|
if (node.type === 'Identifier') {
|
||||||
if (!isDuplicate(node)) {
|
if (!isDuplicate(node)) {
|
||||||
|
// v2 wrapped filter call
|
||||||
|
if (__COMPAT__ && node.name.startsWith('_filter_')) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const needPrefix = shouldPrefix(node, parent!, parentStack)
|
const needPrefix = shouldPrefix(node, parent!, parentStack)
|
||||||
if (!knownIds[node.name] && needPrefix) {
|
if (!knownIds[node.name] && needPrefix) {
|
||||||
if (isStaticProperty(parent!) && parent.shorthand) {
|
if (isStaticProperty(parent!) && parent.shorthand) {
|
||||||
|
@ -271,7 +271,7 @@ export function injectProp(
|
|||||||
|
|
||||||
export function toValidAssetId(
|
export function toValidAssetId(
|
||||||
name: string,
|
name: string,
|
||||||
type: 'component' | 'directive'
|
type: 'component' | 'directive' | 'filter'
|
||||||
): string {
|
): string {
|
||||||
return `_${type}_${name.replace(/[^\w]/g, '_')}`
|
return `_${type}_${name.replace(/[^\w]/g, '_')}`
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ import { isFunction, NO, isObject } from '@vue/shared'
|
|||||||
import { version } from '.'
|
import { version } from '.'
|
||||||
import { installCompatMount } from './compat/global'
|
import { installCompatMount } from './compat/global'
|
||||||
import { installLegacyConfigProperties } from './compat/globalConfig'
|
import { installLegacyConfigProperties } from './compat/globalConfig'
|
||||||
|
import { installGlobalFilterMethod } from './compat/filter'
|
||||||
|
|
||||||
export interface App<HostElement = any> {
|
export interface App<HostElement = any> {
|
||||||
version: string
|
version: string
|
||||||
@ -43,7 +44,13 @@ export interface App<HostElement = any> {
|
|||||||
_context: AppContext
|
_context: AppContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal 2.x compat only
|
* v2 compat only
|
||||||
|
*/
|
||||||
|
filter?(name: string): Function | undefined
|
||||||
|
filter?(name: string, filter: Function): this
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal v3 compat only
|
||||||
*/
|
*/
|
||||||
_createRoot?(options: ComponentOptions): ComponentPublicInstance
|
_createRoot?(options: ComponentOptions): ComponentPublicInstance
|
||||||
}
|
}
|
||||||
@ -92,6 +99,11 @@ export interface AppContext {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
reload?: () => void
|
reload?: () => void
|
||||||
|
/**
|
||||||
|
* v2 compat only
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
filters?: Record<string, Function>
|
||||||
}
|
}
|
||||||
|
|
||||||
type PluginInstallFunction = (app: App, ...options: any[]) => any
|
type PluginInstallFunction = (app: App, ...options: any[]) => any
|
||||||
@ -307,6 +319,7 @@ export function createAppAPI<HostElement>(
|
|||||||
|
|
||||||
if (__COMPAT__) {
|
if (__COMPAT__) {
|
||||||
installCompatMount(app, context, render, hydrate)
|
installCompatMount(app, context, render, hydrate)
|
||||||
|
installGlobalFilterMethod(app, context)
|
||||||
if (__DEV__) installLegacyConfigProperties(app.config)
|
if (__DEV__) installLegacyConfigProperties(app.config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +56,9 @@ export const enum DeprecationTypes {
|
|||||||
COMPONENT_FUNCTIONAL = 'COMPONENT_FUNCTIONAL',
|
COMPONENT_FUNCTIONAL = 'COMPONENT_FUNCTIONAL',
|
||||||
COMPONENT_V_MODEL = 'COMPONENT_V_MODEL',
|
COMPONENT_V_MODEL = 'COMPONENT_V_MODEL',
|
||||||
|
|
||||||
RENDER_FUNCTION = 'RENDER_FUNCTION'
|
RENDER_FUNCTION = 'RENDER_FUNCTION',
|
||||||
|
|
||||||
|
FILTERS = 'FILTERS'
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeprecationData = {
|
type DeprecationData = {
|
||||||
@ -392,6 +394,14 @@ const deprecationData: Record<DeprecationTypes, DeprecationData> = {
|
|||||||
}: false })\n` +
|
}: false })\n` +
|
||||||
`\n (This can also be done per-component via the "compatConfig" option.)`,
|
`\n (This can also be done per-component via the "compatConfig" option.)`,
|
||||||
link: `https://v3.vuejs.org/guide/migration/render-function-api.html`
|
link: `https://v3.vuejs.org/guide/migration/render-function-api.html`
|
||||||
|
},
|
||||||
|
|
||||||
|
[DeprecationTypes.FILTERS]: {
|
||||||
|
message:
|
||||||
|
`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.vuejs.org/guide/migration/filters.html`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
18
packages/runtime-core/src/compat/filter.ts
Normal file
18
packages/runtime-core/src/compat/filter.ts
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { App, AppContext } from '../apiCreateApp'
|
||||||
|
import { warn } from '../warning'
|
||||||
|
import { assertCompatEnabled, DeprecationTypes } from './compatConfig'
|
||||||
|
|
||||||
|
export function installGlobalFilterMethod(app: App, context: AppContext) {
|
||||||
|
context.filters = {}
|
||||||
|
app.filter = (name: string, filter?: Function): any => {
|
||||||
|
assertCompatEnabled(DeprecationTypes.FILTERS, null)
|
||||||
|
if (!filter) {
|
||||||
|
return context.filters![name]
|
||||||
|
}
|
||||||
|
if (__DEV__ && context.filters![name]) {
|
||||||
|
warn(`Filter "${name}" has already been registered.`)
|
||||||
|
}
|
||||||
|
context.filters![name] = filter
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
}
|
@ -268,6 +268,11 @@ export interface ComponentInternalInstance {
|
|||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
directives: Record<string, Directive> | null
|
directives: Record<string, Directive> | null
|
||||||
|
/**
|
||||||
|
* Resolved filters registry, v2 compat only
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
filters?: Record<string, Function>
|
||||||
/**
|
/**
|
||||||
* resolved props options
|
* resolved props options
|
||||||
* @internal
|
* @internal
|
||||||
|
@ -72,6 +72,12 @@ import {
|
|||||||
isCompatEnabled,
|
isCompatEnabled,
|
||||||
softAssertCompatEnabled
|
softAssertCompatEnabled
|
||||||
} from './compat/compatConfig'
|
} from './compat/compatConfig'
|
||||||
|
import {
|
||||||
|
AssetTypes,
|
||||||
|
COMPONENTS,
|
||||||
|
DIRECTIVES,
|
||||||
|
FILTERS
|
||||||
|
} from './helpers/resolveAssets'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Interface for declaring custom options.
|
* Interface for declaring custom options.
|
||||||
@ -413,6 +419,9 @@ interface LegacyOptions<
|
|||||||
provide?: Data | Function
|
provide?: Data | Function
|
||||||
inject?: ComponentInjectOptions
|
inject?: ComponentInjectOptions
|
||||||
|
|
||||||
|
// assets
|
||||||
|
filters?: Record<string, Function>
|
||||||
|
|
||||||
// composition
|
// composition
|
||||||
mixins?: Mixin[]
|
mixins?: Mixin[]
|
||||||
extends?: Extends
|
extends?: Extends
|
||||||
@ -510,9 +519,6 @@ export function applyOptions(
|
|||||||
watch: watchOptions,
|
watch: watchOptions,
|
||||||
provide: provideOptions,
|
provide: provideOptions,
|
||||||
inject: injectOptions,
|
inject: injectOptions,
|
||||||
// assets
|
|
||||||
components,
|
|
||||||
directives,
|
|
||||||
// lifecycle
|
// lifecycle
|
||||||
beforeMount,
|
beforeMount,
|
||||||
mounted,
|
mounted,
|
||||||
@ -721,25 +727,10 @@ export function applyOptions(
|
|||||||
// To reduce memory usage, only components with mixins or extends will have
|
// To reduce memory usage, only components with mixins or extends will have
|
||||||
// resolved asset registry attached to instance.
|
// resolved asset registry attached to instance.
|
||||||
if (asMixin) {
|
if (asMixin) {
|
||||||
if (components) {
|
resolveInstanceAssets(instance, options, COMPONENTS)
|
||||||
extend(
|
resolveInstanceAssets(instance, options, DIRECTIVES)
|
||||||
instance.components ||
|
if (__COMPAT__ && isCompatEnabled(DeprecationTypes.FILTERS, instance)) {
|
||||||
(instance.components = extend(
|
resolveInstanceAssets(instance, options, FILTERS)
|
||||||
{},
|
|
||||||
(instance.type as ComponentOptions).components
|
|
||||||
) as Record<string, ConcreteComponent>),
|
|
||||||
components
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (directives) {
|
|
||||||
extend(
|
|
||||||
instance.directives ||
|
|
||||||
(instance.directives = extend(
|
|
||||||
{},
|
|
||||||
(instance.type as ComponentOptions).directives
|
|
||||||
)),
|
|
||||||
directives
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -818,6 +809,23 @@ export function applyOptions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveInstanceAssets(
|
||||||
|
instance: ComponentInternalInstance,
|
||||||
|
mixin: ComponentOptions,
|
||||||
|
type: AssetTypes
|
||||||
|
) {
|
||||||
|
if (mixin[type]) {
|
||||||
|
extend(
|
||||||
|
instance[type] ||
|
||||||
|
(instance[type] = extend(
|
||||||
|
{},
|
||||||
|
(instance.type as ComponentOptions)[type]
|
||||||
|
) as any),
|
||||||
|
mixin[type]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function resolveInjections(
|
export function resolveInjections(
|
||||||
injectOptions: ComponentInjectOptions,
|
injectOptions: ComponentInjectOptions,
|
||||||
ctx: any,
|
ctx: any,
|
||||||
|
@ -10,8 +10,11 @@ import { camelize, capitalize, isString } from '@vue/shared'
|
|||||||
import { warn } from '../warning'
|
import { warn } from '../warning'
|
||||||
import { VNodeTypes } from '../vnode'
|
import { VNodeTypes } from '../vnode'
|
||||||
|
|
||||||
const COMPONENTS = 'components'
|
export const COMPONENTS = 'components'
|
||||||
const DIRECTIVES = 'directives'
|
export const DIRECTIVES = 'directives'
|
||||||
|
export const FILTERS = 'filters'
|
||||||
|
|
||||||
|
export type AssetTypes = typeof COMPONENTS | typeof DIRECTIVES | typeof FILTERS
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
@ -44,6 +47,14 @@ export function resolveDirective(name: string): Directive | undefined {
|
|||||||
return resolveAsset(DIRECTIVES, name)
|
return resolveAsset(DIRECTIVES, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v2 compat only
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
export function resolveFilter(name: string): Function | undefined {
|
||||||
|
return resolveAsset(FILTERS, name)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* overload 1: components
|
* overload 1: components
|
||||||
@ -60,8 +71,11 @@ function resolveAsset(
|
|||||||
name: string
|
name: string
|
||||||
): Directive | undefined
|
): Directive | undefined
|
||||||
// implementation
|
// implementation
|
||||||
|
// overload 3: filters (compat only)
|
||||||
|
function resolveAsset(type: typeof FILTERS, name: string): Function | undefined
|
||||||
|
// implementation
|
||||||
function resolveAsset(
|
function resolveAsset(
|
||||||
type: typeof COMPONENTS | typeof DIRECTIVES,
|
type: AssetTypes,
|
||||||
name: string,
|
name: string,
|
||||||
warnMissing = true,
|
warnMissing = true,
|
||||||
maybeSelfReference = false
|
maybeSelfReference = false
|
||||||
|
@ -293,6 +293,12 @@ import {
|
|||||||
checkCompatEnabled,
|
checkCompatEnabled,
|
||||||
softAssertCompatEnabled
|
softAssertCompatEnabled
|
||||||
} from './compat/compatConfig'
|
} from './compat/compatConfig'
|
||||||
|
import { resolveFilter as _resolveFilter } from './helpers/resolveAssets'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal only exposed in compat builds
|
||||||
|
*/
|
||||||
|
export const resolveFilter = __COMPAT__ ? _resolveFilter : null
|
||||||
|
|
||||||
const _compatUtils = {
|
const _compatUtils = {
|
||||||
warnDeprecation,
|
warnDeprecation,
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
"formats": [
|
"formats": [
|
||||||
"global"
|
"global"
|
||||||
],
|
],
|
||||||
|
"compat": true,
|
||||||
"env": "development",
|
"env": "development",
|
||||||
"enableNonBrowserBranches": true
|
"enableNonBrowserBranches": true
|
||||||
},
|
},
|
||||||
|
@ -8,12 +8,12 @@ export const compilerOptions: CompilerOptions = reactive({
|
|||||||
mode: 'module',
|
mode: 'module',
|
||||||
filename: 'Foo.vue',
|
filename: 'Foo.vue',
|
||||||
prefixIdentifiers: false,
|
prefixIdentifiers: false,
|
||||||
optimizeImports: false,
|
|
||||||
hoistStatic: false,
|
hoistStatic: false,
|
||||||
cacheHandlers: false,
|
cacheHandlers: false,
|
||||||
scopeId: null,
|
scopeId: null,
|
||||||
inline: false,
|
inline: false,
|
||||||
ssrCssVars: `{ color }`,
|
ssrCssVars: `{ color }`,
|
||||||
|
compatConfig: { MODE: 3 },
|
||||||
bindingMetadata: {
|
bindingMetadata: {
|
||||||
TestComponent: BindingTypes.SETUP_CONST,
|
TestComponent: BindingTypes.SETUP_CONST,
|
||||||
setupRef: BindingTypes.SETUP_REF,
|
setupRef: BindingTypes.SETUP_REF,
|
||||||
@ -170,18 +170,20 @@ const App = {
|
|||||||
h('label', { for: 'inline' }, 'inline')
|
h('label', { for: 'inline' }, 'inline')
|
||||||
]),
|
]),
|
||||||
|
|
||||||
// toggle optimizeImports
|
// compat mode
|
||||||
h('li', [
|
h('li', [
|
||||||
h('input', {
|
h('input', {
|
||||||
type: 'checkbox',
|
type: 'checkbox',
|
||||||
id: 'optimize-imports',
|
id: 'compat',
|
||||||
disabled: !isModule || isSSR,
|
checked: compilerOptions.compatConfig!.MODE === 2,
|
||||||
checked: isModule && !isSSR && compilerOptions.optimizeImports,
|
|
||||||
onChange(e: Event) {
|
onChange(e: Event) {
|
||||||
compilerOptions.optimizeImports = (e.target as HTMLInputElement).checked
|
compilerOptions.compatConfig!.MODE = (e.target as HTMLInputElement)
|
||||||
|
.checked
|
||||||
|
? 2
|
||||||
|
: 3
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
h('label', { for: 'optimize-imports' }, 'optimizeImports')
|
h('label', { for: 'compat' }, 'v2 compat mode')
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
])
|
])
|
||||||
|
Loading…
Reference in New Issue
Block a user