Răsfoiți Sursa

wip(compiler): adjust statement positions

Evan You 6 ani în urmă
părinte
comite
ff2313e43a

+ 5 - 5
packages/compiler-core/__tests__/__snapshots__/codegen.spec.ts.snap

@@ -71,10 +71,10 @@ return function render() {
 `;
 
 exports[`compiler: codegen function mode preamble 1`] = `
-"const { helperOne, helperTwo } = Vue
-
+"const _Vue = Vue
 return function render() {
   with (this) {
+    const { helperOne, helperTwo } = _Vue
     return null
   }
 }"
@@ -147,10 +147,10 @@ return function render() {
 exports[`compiler: codegen statements 1`] = `
 "
 return function render() {
-  const a = 1
-  const b = 2
-  
   with (this) {
+    const a = 1
+    const b = 2
+    
     return null
   }
 }"

+ 2 - 1
packages/compiler-core/__tests__/codegen.spec.ts

@@ -55,7 +55,8 @@ describe('compiler: codegen', () => {
       imports: [`helperOne`, `helperTwo`]
     })
     const { code } = generate(root, { mode: 'function' })
-    expect(code).toMatch(`const { helperOne, helperTwo } = Vue`)
+    expect(code).toMatch(`const _Vue = Vue`)
+    expect(code).toMatch(`const { helperOne, helperTwo } = _Vue`)
     expect(code).toMatchSnapshot()
   })
 

+ 2 - 2
packages/compiler-core/__tests__/compile.spec.ts

@@ -9,10 +9,10 @@ test('basic source map support', async () => {
     filename: `foo.vue`
   })
   expect(code).toMatch(
-    `const { toString } = Vue
-
+    `const _Vue = Vue
 return function render() {
   with (this) {
+    const { toString } = _Vue
     return [
       "hello ",
       toString(world)

+ 30 - 9
packages/compiler-core/src/codegen.ts

@@ -145,10 +145,20 @@ export function generate(
   const context = createCodegenContext(ast, options)
   const { mode, push, prefixIdentifiers, indent, deindent, newline } = context
   const imports = ast.imports.join(', ')
+
+  // preambles
   if (mode === 'function') {
-    // generate const declarations for helpers
+    // Generate const declaration for helpers
+    // In prefix mode, we place the const declaration at top so it's done
+    // only once; But if we not prefixing, we place the decalration inside the
+    // with block so it doesn't incur the `in` check cost for every helper access.
     if (imports) {
-      push(`const { ${imports} } = Vue\n`)
+      if (prefixIdentifiers) {
+        push(`const { ${imports} } = Vue\n`)
+      } else {
+        // save Vue in a separate variable to avoid collision
+        push(`const _Vue = Vue`)
+      }
     }
     genHoists(ast.hoists, context)
     push(`return `)
@@ -160,8 +170,24 @@ export function generate(
     genHoists(ast.hoists, context)
     push(`export default `)
   }
+
+  // enter render function
   push(`function render() {`)
   indent()
+
+  if (!prefixIdentifiers) {
+    push(`with (this) {`)
+    indent()
+    // function mode const declarations should be inside with block
+    if (mode === 'function' && imports) {
+      push(`const { ${imports} } = _Vue`)
+      newline()
+    }
+  } else {
+    push(`const _ctx = this`)
+    newline()
+  }
+
   // generate asset resolution statements
   if (ast.statements.length) {
     ast.statements.forEach(s => {
@@ -170,13 +196,8 @@ export function generate(
     })
     newline()
   }
-  if (!prefixIdentifiers) {
-    push(`with (this) {`)
-    indent()
-  } else {
-    push(`const _ctx = this`)
-    newline()
-  }
+
+  // generate the VNode tree expression
   push(`return `)
   genChildren(ast.children, context, true /* asRoot */)
   if (!prefixIdentifiers) {

+ 4 - 3
packages/runtime-core/src/componentPublicInstanceProxy.ts

@@ -82,9 +82,10 @@ export const PublicInstanceProxyHandlers = {
     const { renderContext, data, props } = target
     // TODO handle $xxx properties
     return (
-      (data !== EMPTY_OBJ && hasOwn(data, key)) ||
-      hasOwn(renderContext, key) ||
-      hasOwn(props, key)
+      key[0] !== '_' &&
+      ((data !== EMPTY_OBJ && hasOwn(data, key)) ||
+        hasOwn(renderContext, key) ||
+        hasOwn(props, key))
     )
   },
   set(target: ComponentInternalInstance, key: string, value: any): boolean {