refactor: use global whitelist for render proxy has check

This commit is contained in:
Evan You 2019-10-02 10:37:06 -04:00
parent d87255ce46
commit 191db785bd
4 changed files with 20 additions and 23 deletions

View File

@ -23,6 +23,7 @@ import {
parseJS, parseJS,
walkJS walkJS
} from '../utils' } from '../utils'
import { globalsWhitelist } from '@vue/shared'
export const transformExpression: NodeTransform = (node, context) => { export const transformExpression: NodeTransform = (node, context) => {
if (node.type === NodeTypes.INTERPOLATION) { if (node.type === NodeTypes.INTERPOLATION) {
@ -215,17 +216,6 @@ const isPropertyShorthand = (node: Node, parent: Node) =>
const isStaticPropertyKey = (node: Node, parent: Node) => const isStaticPropertyKey = (node: Node, parent: Node) =>
isPropertyKey(node, parent) && (parent as Property).value !== node isPropertyKey(node, parent) && (parent as Property).value !== node
const globals = 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,' +
'require,' + // for webpack
'arguments,'
) // parsed as identifier but is a special keyword...
.split(',')
)
function shouldPrefix(identifier: Identifier, parent: Node) { function shouldPrefix(identifier: Identifier, parent: Node) {
if ( if (
!( !(
@ -245,8 +235,12 @@ function shouldPrefix(identifier: Identifier, parent: Node) {
) && ) &&
// not in an Array destructure pattern // not in an Array destructure pattern
!(parent.type === 'ArrayPattern') && !(parent.type === 'ArrayPattern') &&
// skip globals + commonly used shorthands // skip whitelisted globals
!globals.has(identifier.name) !globalsWhitelist.has(identifier.name) &&
// special case for webpack compilation
identifier.name !== `require` &&
// is a special keyword but parsed as identifier
identifier.name !== `arguments`
) { ) {
return true return true
} }

View File

@ -1,7 +1,7 @@
import { ComponentInternalInstance, Data } from './component' import { ComponentInternalInstance, Data } from './component'
import { nextTick } from './scheduler' import { nextTick } from './scheduler'
import { instanceWatch } from './apiWatch' import { instanceWatch } from './apiWatch'
import { EMPTY_OBJ, hasOwn } from '@vue/shared' import { EMPTY_OBJ, hasOwn, globalsWhitelist } from '@vue/shared'
import { ExtracComputedReturns } from './apiOptions' import { ExtracComputedReturns } from './apiOptions'
import { UnwrapRef } from '@vue/reactivity' import { UnwrapRef } from '@vue/reactivity'
@ -78,15 +78,10 @@ export const PublicInstanceProxyHandlers = {
} }
} }
}, },
has(target: ComponentInternalInstance, key: string): boolean { // this trap is only called in browser-compiled render functions that use
const { renderContext, data, props } = target // `with (this) {}`
// TODO handle $xxx properties has(_: any, key: string): boolean {
return ( return key[0] !== '_' && !globalsWhitelist.has(key)
key[0] !== '_' &&
((data !== EMPTY_OBJ && hasOwn(data, key)) ||
hasOwn(renderContext, key) ||
hasOwn(props, key))
)
}, },
set(target: ComponentInternalInstance, key: string, value: any): boolean { set(target: ComponentInternalInstance, key: string, value: any): boolean {
const { data, renderContext } = target const { data, renderContext } = target

View File

@ -0,0 +1,7 @@
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'
).split(',')
)

View File

@ -1,4 +1,5 @@
export * from './patchFlags' export * from './patchFlags'
export { globalsWhitelist } from './globalsWhitelist'
export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__ export const EMPTY_OBJ: { readonly [key: string]: any } = __DEV__
? Object.freeze({}) ? Object.freeze({})