From 31a3454ba33dd439e634f33ca79e4ce080fe5323 Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Mon, 14 Oct 2019 23:45:26 +0530 Subject: [PATCH 1/4] refactor(compiler-core,runtime-core,shared): use plain-object instead of sets checks --- .../src/transforms/transformExpression.ts | 10 +- packages/runtime-core/src/componentProxy.ts | 4 +- packages/shared/src/element.ts | 180 ++---------------- packages/shared/src/globalsWhitelist.ts | 31 +-- packages/shared/src/index.ts | 3 +- packages/shared/src/utils.ts | 15 ++ 6 files changed, 41 insertions(+), 202 deletions(-) create mode 100644 packages/shared/src/utils.ts diff --git a/packages/compiler-core/src/transforms/transformExpression.ts b/packages/compiler-core/src/transforms/transformExpression.ts index e3c2c028b80..6003fe8b319 100644 --- a/packages/compiler-core/src/transforms/transformExpression.ts +++ b/packages/compiler-core/src/transforms/transformExpression.ts @@ -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) { @@ -86,8 +86,8 @@ export function processExpression( if ( !asParams && !context.identifiers[rawExp] && - !globalsWhitelist.has(rawExp) && - !literalsWhitelist.has(rawExp) + !isGloballyWhitelisted(rawExp) && + !isLiteralWhitelisted(rawExp) ) { node.content = `_ctx.${rawExp}` } @@ -246,7 +246,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 diff --git a/packages/runtime-core/src/componentProxy.ts b/packages/runtime-core/src/componentProxy.ts index 02a2ca2d841..3d31bc218ef 100644 --- a/packages/runtime-core/src/componentProxy.ts +++ b/packages/runtime-core/src/componentProxy.ts @@ -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) } } diff --git a/packages/shared/src/element.ts b/packages/shared/src/element.ts index 340d2d8264f..5bb7048c23b 100644 --- a/packages/shared/src/element.ts +++ b/packages/shared/src/element.ts @@ -1,176 +1,18 @@ -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 './utils' + +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) diff --git a/packages/shared/src/globalsWhitelist.ts b/packages/shared/src/globalsWhitelist.ts index 198d66a97e5..71d2dd7cab3 100644 --- a/packages/shared/src/globalsWhitelist.ts +++ b/packages/shared/src/globalsWhitelist.ts @@ -1,25 +1,6 @@ -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 './utils' + +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) diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index f4ce62a49ad..985b101766f 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,6 +1,7 @@ export * from './patchFlags' export * from './element' -export { globalsWhitelist } from './globalsWhitelist' +export { isGloballyWhitelisted } from './globalsWhitelist' +export { makeMap } from './utils' export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__ ? Object.freeze({}) diff --git a/packages/shared/src/utils.ts b/packages/shared/src/utils.ts new file mode 100644 index 00000000000..87291cddc27 --- /dev/null +++ b/packages/shared/src/utils.ts @@ -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 = Object.create(null) + const list: Array = str.split(',') + for (let i = 0; i < list.length; i++) { + map[list[i]] = true + } + return expectsLowerCase ? val => !!map[val.toLowerCase()] : val => !!map[val] +} From 7c07942e3de0d5de815b265b6313cb08b77747f8 Mon Sep 17 00:00:00 2001 From: Ayush Goyal Date: Tue, 15 Oct 2019 08:54:20 +0530 Subject: [PATCH 2/4] refactor(shread): rename the utils to makeMap --- packages/shared/src/element.ts | 2 +- packages/shared/src/globalsWhitelist.ts | 2 +- packages/shared/src/index.ts | 2 +- packages/shared/src/{utils.ts => makeMap.ts} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename packages/shared/src/{utils.ts => makeMap.ts} (100%) diff --git a/packages/shared/src/element.ts b/packages/shared/src/element.ts index 5bb7048c23b..2c90abddd6a 100644 --- a/packages/shared/src/element.ts +++ b/packages/shared/src/element.ts @@ -1,4 +1,4 @@ -import { makeMap } from './utils' +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' diff --git a/packages/shared/src/globalsWhitelist.ts b/packages/shared/src/globalsWhitelist.ts index 71d2dd7cab3..4b8c6bcbe6b 100644 --- a/packages/shared/src/globalsWhitelist.ts +++ b/packages/shared/src/globalsWhitelist.ts @@ -1,4 +1,4 @@ -import { makeMap } from './utils' +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' diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index 985b101766f..fe3d800bacb 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,7 +1,7 @@ export * from './patchFlags' export * from './element' export { isGloballyWhitelisted } from './globalsWhitelist' -export { makeMap } from './utils' +export { makeMap } from './makeMap' export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__ ? Object.freeze({}) diff --git a/packages/shared/src/utils.ts b/packages/shared/src/makeMap.ts similarity index 100% rename from packages/shared/src/utils.ts rename to packages/shared/src/makeMap.ts From 7878ea9f948610b2ea4422ce9845f6b5763d9e80 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 15 Oct 2019 12:04:36 -0400 Subject: [PATCH 3/4] Update element.ts --- packages/shared/src/element.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/shared/src/element.ts b/packages/shared/src/element.ts index 2c90abddd6a..04d5e9fd91d 100644 --- a/packages/shared/src/element.ts +++ b/packages/shared/src/element.ts @@ -1,14 +1,24 @@ 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' + '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 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' + '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 VOID_TAGS = 'area,base,br,col,embed,hr,img,input,link,meta,param,source,track,wbr' From 230f105e1174f09fb811a4023f5e9b9c27723aa8 Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 15 Oct 2019 12:05:21 -0400 Subject: [PATCH 4/4] Update globalsWhitelist.ts --- packages/shared/src/globalsWhitelist.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/shared/src/globalsWhitelist.ts b/packages/shared/src/globalsWhitelist.ts index 4b8c6bcbe6b..8af8c079773 100644 --- a/packages/shared/src/globalsWhitelist.ts +++ b/packages/shared/src/globalsWhitelist.ts @@ -1,6 +1,8 @@ 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' + '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)