Przeglądaj źródła

detect non-existent property access with ES6 Proxy

Evan You 10 lat temu
rodzic
commit
a1ebdbbb7a

+ 6 - 0
src/runtime/instance/index.js

@@ -1,3 +1,4 @@
+import { initProxy } from './proxy'
 import { initState, stateMixin } from './state'
 import { initRender, renderMixin } from './render'
 import { initEvents, eventsMixin } from './events'
@@ -21,6 +22,11 @@ Vue.prototype._init = function (options) {
     options || {},
     this
   )
+  if (process.env.NODE_ENV !== 'production') {
+    initProxy(this)
+  } else {
+    this._renderProxy = this
+  }
   initLifecycle(this)
   initEvents(this)
   callHook(this, 'init')

+ 34 - 0
src/runtime/instance/proxy.js

@@ -0,0 +1,34 @@
+import { warn } from '../util/index'
+
+let hasProxy, proxyHandlers, initProxy
+
+if (process.env.NODE_ENV !== 'production') {
+  hasProxy =
+    typeof Proxy !== 'undefined' &&
+    Proxy.toString().match(/native code/)
+
+  proxyHandlers = {
+    has (target, key) {
+      if (key === 'undefined') {
+        return false
+      }
+      if (!(key in target)) {
+        warn(
+          `Trying to access non-existent property "${key}" while rendering.`,
+          target
+        )
+      }
+      return true
+    }
+  }
+
+  initProxy = function initProxy (vm) {
+    if (hasProxy) {
+      vm._renderProxy = new Proxy(vm, proxyHandlers)
+    } else {
+      vm._renderProxy = vm
+    }
+  }
+}
+
+export { initProxy }

+ 1 - 1
src/runtime/instance/render.js

@@ -138,7 +138,7 @@ export function renderMixin (Vue) {
       resolveSlots(this, _renderChildren)
     }
     // render self
-    const vnode = render.call(this)
+    const vnode = render.call(this._renderProxy)
     // update parent data
     if (_renderData) {
       mergeParentData(this, vnode.data, _renderData)