Browse Source

Merge pull request #2 from HugoDF/feat-pass-el-to-eval

pass el + move tryCatch in eval functions
Hugo 4 years ago
parent
commit
6358d2c30a
2 changed files with 42 additions and 38 deletions
  1. 7 7
      src/component.js
  2. 35 31
      src/utils.js

+ 7 - 7
src/component.js

@@ -1,4 +1,4 @@
-import { walk, tryCatch, saferEval, saferEvalNoReturn, getXAttrs, debounce, convertClassStringToArray, TRANSITION_CANCELLED } from './utils'
+import { walk, saferEval, saferEvalNoReturn, getXAttrs, debounce, convertClassStringToArray, TRANSITION_CANCELLED } from './utils'
 import { handleForDirective } from './directives/for'
 import { handleAttributeBindingDirective } from './directives/bind'
 import { handleTextDirective } from './directives/text'
@@ -28,7 +28,7 @@ export default class Component {
             Object.defineProperty(dataExtras, `$${name}`, { get: function () { return callback(canonicalComponentElementReference) } });
         })
 
-        this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : tryCatch(() => saferEval(dataExpression, dataExtras), { el, expression: dataExpression })
+        this.unobservedData = componentForClone ? componentForClone.getUnobservedData() : saferEval(el, dataExpression, dataExtras)
 
         /* IE11-ONLY:START */
             // For IE11, add our magic properties to the original data for access.
@@ -351,17 +351,17 @@ export default class Component {
     }
 
     evaluateReturnExpression(el, expression, extraVars = () => {}) {
-        return tryCatch(() => saferEval(expression, this.$data, {
+        return saferEval(el, expression, this.$data, {
             ...extraVars(),
             $dispatch: this.getDispatchFunction(el),
-        }), { el, expression })
+        })
     }
 
     evaluateCommandExpression(el, expression, extraVars = () => {}) {
-        return tryCatch(() => saferEvalNoReturn(expression, this.$data, {
+        return saferEvalNoReturn(el, expression, this.$data, {
             ...extraVars(),
             $dispatch: this.getDispatchFunction(el),
-        }), { el, expression })
+        })
     }
 
     getDispatchFunction (el) {
@@ -391,7 +391,7 @@ export default class Component {
 
                 if (mutations[i].type === 'attributes' && mutations[i].attributeName === 'x-data') {
                     const xAttr = mutations[i].target.getAttribute('x-data') || '{}';
-                    const rawData = tryCatch(() => saferEval(xAttr, { $el: this.$el }), { el: this.$el, xAttr })
+                    const rawData = saferEval(this.$el, xAttr, { $el: this.$el })
 
                     Object.keys(rawData).forEach(key => {
                         if (this.$data[key] !== rawData[key]) {

+ 35 - 31
src/utils.js

@@ -72,7 +72,7 @@ const handleError = (el, expression, error) => {
     }
 }
 
-export function tryCatch(cb, { el, expression }) {
+function tryCatch(cb, { el, expression }) {
     try {
         const value = cb();
         return value instanceof Promise
@@ -83,44 +83,48 @@ export function tryCatch(cb, { el, expression }) {
     }
 }
 
-export function saferEval(expression, dataContext, additionalHelperVariables = {}) {
-    if (typeof expression === 'function') {
-        return expression.call(dataContext)
-    }
+export function saferEval(el, expression, dataContext, additionalHelperVariables = {}) {
+    return tryCatch(() => {
+        if (typeof expression === 'function') {
+            return expression.call(dataContext)
+        }
 
-    return (new Function(['$data', ...Object.keys(additionalHelperVariables)], `var __alpine_result; with($data) { __alpine_result = ${expression} }; return __alpine_result`))(
-        dataContext, ...Object.values(additionalHelperVariables)
-    )
+        return (new Function(['$data', ...Object.keys(additionalHelperVariables)], `var __alpine_result; with($data) { __alpine_result = ${expression} }; return __alpine_result`))(
+            dataContext, ...Object.values(additionalHelperVariables)
+        )
+    }, { el, expression })
 }
 
-export function saferEvalNoReturn(expression, dataContext, additionalHelperVariables = {}) {
-    if (typeof expression === 'function') {
-        return Promise.resolve(expression.call(dataContext, additionalHelperVariables['$event']))
-    }
+export function saferEvalNoReturn(el, expression, dataContext, additionalHelperVariables = {}) {
+    return tryCatch(() => {
+        if (typeof expression === 'function') {
+            return Promise.resolve(expression.call(dataContext, additionalHelperVariables['$event']))
+        }
 
-    let AsyncFunction = Function
+        let AsyncFunction = Function
 
-    /* MODERN-ONLY:START */
-        AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
-    /* MODERN-ONLY:END */
+        /* MODERN-ONLY:START */
+            AsyncFunction = Object.getPrototypeOf(async function(){}).constructor
+        /* MODERN-ONLY:END */
 
-    // For the cases when users pass only a function reference to the caller: `x-on:click="foo"`
-    // Where "foo" is a function. Also, we'll pass the function the event instance when we call it.
-    if (Object.keys(dataContext).includes(expression)) {
-        let methodReference = (new Function(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { return ${expression} }`))(
-            dataContext, ...Object.values(additionalHelperVariables)
-        )
+        // For the cases when users pass only a function reference to the caller: `x-on:click="foo"`
+        // Where "foo" is a function. Also, we'll pass the function the event instance when we call it.
+        if (Object.keys(dataContext).includes(expression)) {
+            let methodReference = (new Function(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { return ${expression} }`))(
+                dataContext, ...Object.values(additionalHelperVariables)
+            )
 
-        if (typeof methodReference === 'function') {
-            return Promise.resolve(methodReference.call(dataContext, additionalHelperVariables['$event']))
-        } else {
-            return Promise.resolve()
+            if (typeof methodReference === 'function') {
+                return Promise.resolve(methodReference.call(dataContext, additionalHelperVariables['$event']))
+            } else {
+                return Promise.resolve()
+            }
         }
-    }
 
-    return Promise.resolve((new AsyncFunction(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { ${expression} }`))(
-        dataContext, ...Object.values(additionalHelperVariables)
-    ))
+        return Promise.resolve((new AsyncFunction(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { ${expression} }`))(
+            dataContext, ...Object.values(additionalHelperVariables)
+        ))
+    }, { el, expression })
 }
 
 const xAttrRE = /^x-(on|bind|data|text|html|model|if|for|show|cloak|transition|ref|spread)\b/
@@ -139,7 +143,7 @@ export function getXAttrs(el, component, type) {
 
     if (spreadDirective) {
         const { expression } = spreadDirective
-        let spreadObject = tryCatch(() => saferEval(expression, component.$data), { expression, el })
+        let spreadObject = saferEval(el, expression, component.$data)
 
         // Add x-spread directives to the pile of existing directives.
         directives = directives.concat(Object.entries(spreadObject).map(([name, value]) => parseHtmlAttribute({ name, value })))