mirror of
https://gitee.com/vuejs/vue.git
synced 2024-11-30 02:57:43 +08:00
wip: handle script analyzed bindings when prefixing identifiers
This commit is contained in:
parent
903d9b2eb6
commit
452aa9d29c
@ -1209,7 +1209,11 @@ export function compileScript(
|
||||
allBindings[key] = true
|
||||
}
|
||||
}
|
||||
const returned = `{ ${Object.keys(allBindings).join(', ')} }`
|
||||
// __sfc marker indicates these bindings are compiled from <script setup>
|
||||
// and should not be proxied on `this`
|
||||
const returned = `{ ${__TEST__ ? `` : `__sfc: true,`}${Object.keys(
|
||||
allBindings
|
||||
).join(', ')} }`
|
||||
|
||||
s.appendRight(endOffset, `\nreturn ${returned}\n}\n\n`)
|
||||
|
||||
|
@ -1,4 +1,8 @@
|
||||
import { VueTemplateCompiler, VueTemplateCompilerOptions } from './types'
|
||||
import {
|
||||
BindingMetadata,
|
||||
VueTemplateCompiler,
|
||||
VueTemplateCompilerOptions
|
||||
} from './types'
|
||||
import assetUrlsModule, {
|
||||
AssetURLOptions,
|
||||
TransformAssetUrlsOptions
|
||||
@ -6,7 +10,7 @@ import assetUrlsModule, {
|
||||
import srcsetModule from './templateCompilerModules/srcset'
|
||||
import consolidate from '@vue/consolidate'
|
||||
import * as _compiler from 'web/entry-compiler'
|
||||
import { stripWith } from './stripWith'
|
||||
import { prefixIdentifiers } from './prefixIdentifiers'
|
||||
import { WarningMessage } from 'types/compiler'
|
||||
|
||||
export interface TemplateCompileOptions {
|
||||
@ -24,6 +28,7 @@ export interface TemplateCompileOptions {
|
||||
optimizeSSR?: boolean
|
||||
prettify?: boolean
|
||||
isTS?: boolean
|
||||
bindings?: BindingMetadata
|
||||
}
|
||||
|
||||
export interface TemplateCompileResult {
|
||||
@ -107,7 +112,8 @@ function actuallyCompile(
|
||||
isFunctional = false,
|
||||
optimizeSSR = false,
|
||||
prettify = true,
|
||||
isTS = false
|
||||
isTS = false,
|
||||
bindings
|
||||
} = options
|
||||
|
||||
const compile =
|
||||
@ -144,15 +150,23 @@ function actuallyCompile(
|
||||
// transpile code with vue-template-es2015-compiler, which is a forked
|
||||
// version of Buble that applies ES2015 transforms + stripping `with` usage
|
||||
let code =
|
||||
`var __render__ = ${stripWith(
|
||||
`var __render__ = ${prefixIdentifiers(
|
||||
render,
|
||||
`render`,
|
||||
isFunctional,
|
||||
isTS,
|
||||
transpileOptions
|
||||
transpileOptions,
|
||||
bindings
|
||||
)}\n` +
|
||||
`var __staticRenderFns__ = [${staticRenderFns.map(code =>
|
||||
stripWith(code, ``, isFunctional, isTS, transpileOptions)
|
||||
prefixIdentifiers(
|
||||
code,
|
||||
``,
|
||||
isFunctional,
|
||||
isTS,
|
||||
transpileOptions,
|
||||
bindings
|
||||
)
|
||||
)}]` +
|
||||
`\n`
|
||||
|
||||
|
@ -2,6 +2,7 @@ import MagicString from 'magic-string'
|
||||
import { parseExpression, ParserOptions, ParserPlugin } from '@babel/parser'
|
||||
import { makeMap } from 'shared/util'
|
||||
import { walkIdentifiers } from './babelUtils'
|
||||
import { BindingMetadata } from './types'
|
||||
|
||||
const doNotPrefix = makeMap(
|
||||
'Infinity,undefined,NaN,isFinite,isNaN,' +
|
||||
@ -16,12 +17,13 @@ const doNotPrefix = makeMap(
|
||||
* The input is expected to be the render function code directly returned from
|
||||
* `compile()` calls, e.g. `with(this){return ...}`
|
||||
*/
|
||||
export function stripWith(
|
||||
export function prefixIdentifiers(
|
||||
source: string,
|
||||
fnName = '',
|
||||
isFunctional = false,
|
||||
isTS = false,
|
||||
babelOptions: ParserOptions = {}
|
||||
babelOptions: ParserOptions = {},
|
||||
bindings?: BindingMetadata
|
||||
) {
|
||||
source = `function ${fnName}(${isFunctional ? `_c,_vm` : ``}){${source}\n}`
|
||||
|
||||
@ -40,17 +42,29 @@ export function stripWith(
|
||||
walkIdentifiers(
|
||||
ast,
|
||||
ident => {
|
||||
if (doNotPrefix(ident.name)) {
|
||||
const { name } = ident
|
||||
if (doNotPrefix(name)) {
|
||||
return
|
||||
}
|
||||
s.prependRight(ident.start!, '_vm.')
|
||||
|
||||
if (!bindings) {
|
||||
s.prependRight(ident.start!, '_vm.')
|
||||
return
|
||||
}
|
||||
|
||||
s.overwrite(ident.start!, ident.end!, rewriteIdentifier(name, bindings))
|
||||
},
|
||||
node => {
|
||||
if (node.type === 'WithStatement') {
|
||||
s.remove(node.start!, node.body.start! + 1)
|
||||
s.remove(node.end! - 1, node.end!)
|
||||
if (!isFunctional) {
|
||||
s.prependRight(node.start!, `var _vm=this;var _c=_vm._self._c;`)
|
||||
s.prependRight(
|
||||
node.start!,
|
||||
`var _vm=this,_c=_vm._self._c${
|
||||
bindings ? `,_setup=_vm._setupProxy;` : `;`
|
||||
}`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -58,3 +72,15 @@ export function stripWith(
|
||||
|
||||
return s.toString()
|
||||
}
|
||||
|
||||
export function rewriteIdentifier(
|
||||
name: string,
|
||||
bindings: BindingMetadata
|
||||
): string {
|
||||
const type = bindings[name]
|
||||
if (type && type.startsWith('setup')) {
|
||||
return `_setup.${name}`
|
||||
} else {
|
||||
return `_vm.${name}`
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { stripWith } from '../src/stripWith'
|
||||
import { prefixIdentifiers } from '../src/prefixIdentifiers'
|
||||
import { compile } from 'web/entry-compiler'
|
||||
import { format } from 'prettier'
|
||||
|
||||
@ -11,7 +11,7 @@ it('should work', () => {
|
||||
</foo>
|
||||
</div>`)
|
||||
|
||||
const result = format(stripWith(render, `render`), {
|
||||
const result = format(prefixIdentifiers(render, `render`), {
|
||||
semi: false,
|
||||
parser: 'babel'
|
||||
})
|
||||
@ -24,8 +24,8 @@ it('should work', () => {
|
||||
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
"function render() {
|
||||
var _vm = this
|
||||
var _c = _vm._self._c
|
||||
var _vm = this,
|
||||
_c = _vm._self._c
|
||||
return _c(
|
||||
\\"div\\",
|
||||
{ attrs: { id: \\"app\\" } },
|
||||
@ -39,8 +39,8 @@ it('should work', () => {
|
||||
_c(\\"foo\\", {
|
||||
inlineTemplate: {
|
||||
render: function () {
|
||||
var _vm = this
|
||||
var _c = _vm._self._c
|
||||
var _vm = this,
|
||||
_c = _vm._self._c
|
||||
return _c(\\"div\\", [_vm._v(_vm._s(_vm.bar))])
|
||||
},
|
||||
staticRenderFns: [],
|
@ -278,7 +278,8 @@ function genConfig(name) {
|
||||
// built-in vars
|
||||
const vars = {
|
||||
__VERSION__: version,
|
||||
__DEV__: `process.env.NODE_ENV !== 'production'`
|
||||
__DEV__: `process.env.NODE_ENV !== 'production'`,
|
||||
__TEST__: false
|
||||
}
|
||||
// feature flags
|
||||
Object.keys(featureFlags).forEach(key => {
|
||||
|
1
src/global.d.ts
vendored
1
src/global.d.ts
vendored
@ -1,4 +1,5 @@
|
||||
declare const __DEV__: boolean
|
||||
declare const __TEST__: boolean
|
||||
|
||||
interface Window {
|
||||
__VUE_DEVTOOLS_GLOBAL_HOOK__: DevtoolsHook
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { BindingMetadata } from 'sfc/types'
|
||||
|
||||
export type CompilerOptions = {
|
||||
warn?: Function // allow customizing warning in different environments; e.g. node
|
||||
modules?: Array<ModuleOptions> // platform specific modules; e.g. style; class
|
||||
@ -28,6 +30,8 @@ export type CompilerOptions = {
|
||||
|
||||
// for ssr optimization compiler
|
||||
scopeId?: string
|
||||
|
||||
bindingMetadata?: BindingMetadata
|
||||
}
|
||||
|
||||
export type WarningMessage = {
|
||||
|
@ -108,6 +108,7 @@ export declare class Component {
|
||||
|
||||
// @v3
|
||||
_setupState?: Record<string, any>
|
||||
_setupProxy?: Record<string, any>
|
||||
_setupContext?: SetupContext
|
||||
_attrsProxy?: Record<string, any>
|
||||
_slotsProxy?: Record<string, () => VNode[]>
|
||||
|
@ -43,11 +43,20 @@ export function initSetup(vm: Component) {
|
||||
)
|
||||
}
|
||||
vm._setupState = setupResult
|
||||
for (const key in setupResult) {
|
||||
if (!isReserved(key)) {
|
||||
proxySetupProperty(vm, setupResult, key)
|
||||
} else if (__DEV__) {
|
||||
warn(`Avoid using variables that start with _ or $ in setup().`)
|
||||
// __sfc indicates compiled bindings from <script setup>
|
||||
if (!setupResult.__sfc) {
|
||||
for (const key in setupResult) {
|
||||
if (!isReserved(key)) {
|
||||
proxySetupProperty(vm, setupResult, key)
|
||||
} else if (__DEV__) {
|
||||
warn(`Avoid using variables that start with _ or $ in setup().`)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// exposed for compiled render fn
|
||||
const proxy = (vm._setupProxy = {})
|
||||
for (const key in setupResult) {
|
||||
proxySetupProperty(proxy, setupResult, key)
|
||||
}
|
||||
}
|
||||
} else if (__DEV__ && setupResult !== undefined) {
|
||||
@ -61,17 +70,17 @@ export function initSetup(vm: Component) {
|
||||
}
|
||||
|
||||
function proxySetupProperty(
|
||||
vm: Component,
|
||||
target: any,
|
||||
setupResult: Record<string, any>,
|
||||
key: string
|
||||
) {
|
||||
const raw = setupResult[key]
|
||||
const unwrap = isRef(raw)
|
||||
Object.defineProperty(vm, key, {
|
||||
let raw = setupResult[key]
|
||||
Object.defineProperty(target, key, {
|
||||
enumerable: true,
|
||||
configurable: true,
|
||||
get: unwrap ? () => raw.value : () => setupResult[key],
|
||||
set: unwrap ? v => (raw.value = v) : v => (setupResult[key] = v)
|
||||
get: () => (isRef(raw) ? raw.value : raw),
|
||||
set: newVal =>
|
||||
isRef(raw) ? (raw.value = newVal) : (raw = setupResult[key] = newVal)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -17,7 +17,8 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
define: {
|
||||
__DEV__: true
|
||||
__DEV__: true,
|
||||
__TEST__: true
|
||||
},
|
||||
test: {
|
||||
globals: true,
|
||||
|
Loading…
Reference in New Issue
Block a user