refactor(core): use makeMap for faster string match checks (#282)
This commit is contained in:
parent
eb28d45933
commit
58fffcb987
@ -23,9 +23,9 @@ import {
|
||||
parseJS,
|
||||
walkJS
|
||||
} from '../utils'
|
||||
import { globalsWhitelist } from '@vue/shared'
|
||||
import { isGloballyWhitelisted, makeMap } from '@vue/shared'
|
||||
|
||||
const literalsWhitelist = new Set([`true`, `false`, `null`, `this`])
|
||||
const isLiteralWhitelisted = makeMap('true,false,null,this')
|
||||
|
||||
export const transformExpression: NodeTransform = (node, context) => {
|
||||
if (node.type === NodeTypes.INTERPOLATION) {
|
||||
@ -87,8 +87,8 @@ export function processExpression(
|
||||
if (
|
||||
!asParams &&
|
||||
!context.identifiers[rawExp] &&
|
||||
!globalsWhitelist.has(rawExp) &&
|
||||
!literalsWhitelist.has(rawExp)
|
||||
!isGloballyWhitelisted(rawExp) &&
|
||||
!isLiteralWhitelisted(rawExp)
|
||||
) {
|
||||
node.content = `_ctx.${rawExp}`
|
||||
} else if (!context.identifiers[rawExp]) {
|
||||
@ -261,7 +261,7 @@ function shouldPrefix(identifier: Identifier, parent: Node) {
|
||||
// not in an Array destructure pattern
|
||||
!(parent.type === 'ArrayPattern') &&
|
||||
// skip whitelisted globals
|
||||
!globalsWhitelist.has(identifier.name) &&
|
||||
!isGloballyWhitelisted(identifier.name) &&
|
||||
// special case for webpack compilation
|
||||
identifier.name !== `require` &&
|
||||
// is a special keyword but parsed as identifier
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ComponentInternalInstance, Data } from './component'
|
||||
import { nextTick } from './scheduler'
|
||||
import { instanceWatch } from './apiWatch'
|
||||
import { EMPTY_OBJ, hasOwn, globalsWhitelist } from '@vue/shared'
|
||||
import { EMPTY_OBJ, hasOwn, isGloballyWhitelisted } from '@vue/shared'
|
||||
import { ExtractComputedReturns } from './apiOptions'
|
||||
import { UnwrapRef, ReactiveEffect } from '@vue/reactivity'
|
||||
import { warn } from './warning'
|
||||
@ -106,6 +106,6 @@ if (__RUNTIME_COMPILE__) {
|
||||
// this trap is only called in browser-compiled render functions that use
|
||||
// `with (this) {}`
|
||||
PublicInstanceProxyHandlers.has = (_: any, key: string): boolean => {
|
||||
return key[0] !== '_' && !globalsWhitelist.has(key)
|
||||
return key[0] !== '_' && !isGloballyWhitelisted(key)
|
||||
}
|
||||
}
|
||||
|
@ -1,176 +1,28 @@
|
||||
const HTMLTagSet = new Set([
|
||||
'html',
|
||||
'body',
|
||||
'base',
|
||||
'head',
|
||||
'link',
|
||||
'meta',
|
||||
'style',
|
||||
'title',
|
||||
'address',
|
||||
'article',
|
||||
'aside',
|
||||
'footer',
|
||||
'header',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'hgroup',
|
||||
'nav',
|
||||
'section',
|
||||
'div',
|
||||
'dd',
|
||||
'dl',
|
||||
'dt',
|
||||
'figcaption',
|
||||
'figure',
|
||||
'picture',
|
||||
'hr',
|
||||
'img',
|
||||
'li',
|
||||
'main',
|
||||
'ol',
|
||||
'p',
|
||||
'pre',
|
||||
'ul',
|
||||
'a',
|
||||
'b',
|
||||
'abbr',
|
||||
'bdi',
|
||||
'bdo',
|
||||
'br',
|
||||
'cite',
|
||||
'code',
|
||||
'data',
|
||||
'dfn',
|
||||
'em',
|
||||
'i',
|
||||
'kbd',
|
||||
'mark',
|
||||
'q',
|
||||
'rp',
|
||||
'rt',
|
||||
'rtc',
|
||||
'ruby',
|
||||
's',
|
||||
'samp',
|
||||
'small',
|
||||
'span',
|
||||
'strong',
|
||||
'sub',
|
||||
'sup',
|
||||
'time',
|
||||
'u',
|
||||
'var',
|
||||
'wbr',
|
||||
'area',
|
||||
'audio',
|
||||
'map',
|
||||
'track',
|
||||
'video',
|
||||
'embed',
|
||||
'object',
|
||||
'param',
|
||||
'source',
|
||||
'canvas',
|
||||
'script',
|
||||
'noscript',
|
||||
'del',
|
||||
'ins',
|
||||
'caption',
|
||||
'col',
|
||||
'colgroup',
|
||||
'table',
|
||||
'thead',
|
||||
'tbody',
|
||||
'td',
|
||||
'th',
|
||||
'tr',
|
||||
'button',
|
||||
'datalist',
|
||||
'fieldset',
|
||||
'form',
|
||||
'input',
|
||||
'label',
|
||||
'legend',
|
||||
'meter',
|
||||
'optgroup',
|
||||
'option',
|
||||
'output',
|
||||
'progress',
|
||||
'select',
|
||||
'textarea',
|
||||
'details',
|
||||
'dialog',
|
||||
'menu',
|
||||
'menuitem',
|
||||
'summary',
|
||||
'content',
|
||||
'element',
|
||||
'shadow',
|
||||
'template',
|
||||
'blockquote',
|
||||
'iframe',
|
||||
'tfoot'
|
||||
])
|
||||
import { makeMap } from './makeMap'
|
||||
|
||||
const HTML_TAGS =
|
||||
'html,body,base,head,link,meta,style,title,address,article,aside,footer,' +
|
||||
'header,h1,h2,h3,h4,h5,h6,hgroup,nav,section,div,dd,dl,dt,figcaption,' +
|
||||
'figure,picture,hr,img,li,main,ol,p,pre,ul,a,b,abbr,bdi,bdo,br,cite,code,' +
|
||||
'data,dfn,em,i,kbd,mark,q,rp,rt,rtc,ruby,s,samp,small,span,strong,sub,sup,' +
|
||||
'time,u,var,wbr,area,audio,map,track,video,embed,object,param,source,' +
|
||||
'canvas,script,noscript,del,ins,caption,col,colgroup,table,thead,tbody,td,' +
|
||||
'th,tr,button,datalist,fieldset,form,input,label,legend,meter,optgroup,' +
|
||||
'option,output,progress,select,textarea,details,dialog,menu,menuitem,' +
|
||||
'summary,content,element,shadow,template,blockquote,iframe,tfoot'
|
||||
|
||||
/**
|
||||
* this list is intentionally selective, only covering SVG elements that may
|
||||
* contain child elements.
|
||||
*/
|
||||
const SVGTagSet = new Set([
|
||||
'svg',
|
||||
'animate',
|
||||
'circle',
|
||||
'clippath',
|
||||
'cursor',
|
||||
'defs',
|
||||
'desc',
|
||||
'ellipse',
|
||||
'filter',
|
||||
'font-face',
|
||||
'foreignObject',
|
||||
'g',
|
||||
'glyph',
|
||||
'image',
|
||||
'line',
|
||||
'marker',
|
||||
'mask',
|
||||
'missing-glyph',
|
||||
'path',
|
||||
'pattern',
|
||||
'polygon',
|
||||
'polyline',
|
||||
'rect',
|
||||
'switch',
|
||||
'symbol',
|
||||
'text',
|
||||
'textpath',
|
||||
'tspan',
|
||||
'use',
|
||||
'view'
|
||||
])
|
||||
const SVG_TAGS =
|
||||
'svg,animate,circle,clippath,cursor,defs,desc,ellipse,filter,font-face,' +
|
||||
'foreignObject,g,glyph,image,line,marker,mask,missing-glyph,path,pattern,' +
|
||||
'polygon,polyline,rect,switch,symbol,text,textpath,tspan,use,view'
|
||||
|
||||
const VoidTagSet = new Set([
|
||||
'area',
|
||||
'base',
|
||||
'br',
|
||||
'col',
|
||||
'embed',
|
||||
'hr',
|
||||
'img',
|
||||
'input',
|
||||
'link',
|
||||
'meta',
|
||||
'param',
|
||||
'source',
|
||||
'track',
|
||||
'wbr'
|
||||
])
|
||||
const VOID_TAGS =
|
||||
'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr'
|
||||
|
||||
export const isVoidTag = (tag: string) => VoidTagSet.has(tag)
|
||||
export const isHTMLTag = (tag: string) => HTMLTagSet.has(tag)
|
||||
export const isSVGTag = (tag: string) => SVGTagSet.has(tag)
|
||||
export const isHTMLTag = makeMap(HTML_TAGS)
|
||||
export const isSVGTag = makeMap(SVG_TAGS)
|
||||
export const isVoidTag = makeMap(VOID_TAGS)
|
||||
|
@ -1,25 +1,8 @@
|
||||
export const globalsWhitelist = new Set([
|
||||
'Infinity',
|
||||
'undefined',
|
||||
'NaN',
|
||||
'isFinite',
|
||||
'isNaN',
|
||||
'parseFloat',
|
||||
'parseInt',
|
||||
'decodeURI',
|
||||
'decodeURIComponent',
|
||||
'encodeURI',
|
||||
'encodeURIComponent',
|
||||
'Math',
|
||||
'Number',
|
||||
'Date',
|
||||
'Array',
|
||||
'Object',
|
||||
'Boolean',
|
||||
'String',
|
||||
'RegExp',
|
||||
'Map',
|
||||
'Set',
|
||||
'JSON',
|
||||
'Intl'
|
||||
])
|
||||
import { makeMap } from './makeMap'
|
||||
|
||||
const GLOBALS_WHITE_LISTED =
|
||||
'Infinity,undefined,NaN,isFinite,isNaN,parseFloat,parseInt,decodeURI,' +
|
||||
'decodeURIComponent,encodeURI,encodeURIComponent,Math,Number,Date,Array,' +
|
||||
'Object,Boolean,String,RegExp,Map,Set,JSON,Intl'
|
||||
|
||||
export const isGloballyWhitelisted = makeMap(GLOBALS_WHITE_LISTED)
|
||||
|
@ -1,6 +1,7 @@
|
||||
export * from './patchFlags'
|
||||
export * from './element'
|
||||
export { globalsWhitelist } from './globalsWhitelist'
|
||||
export { isGloballyWhitelisted } from './globalsWhitelist'
|
||||
export { makeMap } from './makeMap'
|
||||
|
||||
export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
|
||||
? Object.freeze({})
|
||||
|
15
packages/shared/src/makeMap.ts
Normal file
15
packages/shared/src/makeMap.ts
Normal file
@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Make a map and return a function for checking if a key
|
||||
* is in that map.
|
||||
*/
|
||||
export function makeMap(
|
||||
str: string,
|
||||
expectsLowerCase?: boolean
|
||||
): (key: string) => boolean {
|
||||
const map: Record<string, boolean> = Object.create(null)
|
||||
const list: Array<string> = str.split(',')
|
||||
for (let i = 0; i < list.length; i++) {
|
||||
map[list[i]] = true
|
||||
}
|
||||
return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val]
|
||||
}
|
Loading…
Reference in New Issue
Block a user