From 09d0ed82903d58ac4209620ff87d818e70baac23 Mon Sep 17 00:00:00 2001 From: Chris Vilches Date: Sat, 20 Jul 2024 15:02:17 +0900 Subject: [PATCH 1/4] Export runIfTypeOfFunction and injectMagics so they can be used in plugins --- packages/alpinejs/src/alpine.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/alpinejs/src/alpine.js b/packages/alpinejs/src/alpine.js index cf7081ef6..c2df03eb0 100644 --- a/packages/alpinejs/src/alpine.js +++ b/packages/alpinejs/src/alpine.js @@ -3,7 +3,7 @@ import { mapAttributes, directive, setPrefix as prefix, prefix as prefixed } fro import { start, addRootSelector, addInitSelector, closestRoot, findClosest, initTree, destroyTree, interceptInit } from './lifecycle' import { onElRemoved, onAttributeRemoved, onAttributesAdded, mutateDom, deferMutations, flushAndStopDeferringMutations, startObservingMutations, stopObservingMutations } from './mutation' import { mergeProxies, closestDataStack, addScopeToNode, scope as $data } from './scope' -import { setEvaluator, evaluate, evaluateLater, dontAutoEvaluateFunctions } from './evaluator' +import { setEvaluator, evaluate, evaluateLater, dontAutoEvaluateFunctions, runIfTypeOfFunction } from './evaluator' import { transition } from './directives/x-transition' import { clone, cloneNode, skipDuringClone, onlyDuringClone, interceptClone } from './clone' import { interceptor } from './interceptor' @@ -15,7 +15,7 @@ import { entangle } from './entangle' import { nextTick } from './nextTick' import { walk } from './utils/walk' import { plugin } from './plugin' -import { magic } from './magics' +import { injectMagics, magic } from './magics' import { store } from './store' import { bind } from './binds' import { data } from './datas' @@ -32,6 +32,7 @@ let Alpine = { startObservingMutations, stopObservingMutations, setReactivityEngine, + runIfTypeOfFunction, onAttributeRemoved, onAttributesAdded, closestDataStack, @@ -46,6 +47,7 @@ let Alpine = { evaluateLater, interceptInit, setEvaluator, + injectMagics, mergeProxies, extractProp, findClosest, From 609aaa6cceb79bf02c2b5487bcfa7e1048f09d01 Mon Sep 17 00:00:00 2001 From: Chris Vilches Date: Sat, 20 Jul 2024 15:04:03 +0900 Subject: [PATCH 2/4] attempt to sort imports by string size --- packages/alpinejs/src/alpine.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/alpinejs/src/alpine.js b/packages/alpinejs/src/alpine.js index c2df03eb0..0dfc0250b 100644 --- a/packages/alpinejs/src/alpine.js +++ b/packages/alpinejs/src/alpine.js @@ -6,6 +6,7 @@ import { mergeProxies, closestDataStack, addScopeToNode, scope as $data } from ' import { setEvaluator, evaluate, evaluateLater, dontAutoEvaluateFunctions, runIfTypeOfFunction } from './evaluator' import { transition } from './directives/x-transition' import { clone, cloneNode, skipDuringClone, onlyDuringClone, interceptClone } from './clone' +import { injectMagics, magic } from './magics' import { interceptor } from './interceptor' import { getBinding as bound, extractProp } from './utils/bind' import { debounce } from './utils/debounce' @@ -15,7 +16,6 @@ import { entangle } from './entangle' import { nextTick } from './nextTick' import { walk } from './utils/walk' import { plugin } from './plugin' -import { injectMagics, magic } from './magics' import { store } from './store' import { bind } from './binds' import { data } from './datas' From 8f5086d776940744a1b1cfbd1ca92650182c5608 Mon Sep 17 00:00:00 2001 From: Chris Vilches Date: Sun, 21 Jul 2024 07:59:31 +0900 Subject: [PATCH 3/4] remove dontAutoEvaluateFunctions, refactor, evaluator, and remove exports --- packages/alpinejs/src/alpine.js | 4 +--- packages/alpinejs/src/evaluator.js | 30 ++++++++--------------------- packages/alpinejs/src/utils/bind.js | 6 ++---- packages/csp/src/evaluator.js | 4 ++-- packages/mask/src/index.js | 11 ++++++----- packages/sort/src/index.js | 23 +++++++++++----------- 6 files changed, 31 insertions(+), 47 deletions(-) diff --git a/packages/alpinejs/src/alpine.js b/packages/alpinejs/src/alpine.js index 0dfc0250b..8b297dfec 100644 --- a/packages/alpinejs/src/alpine.js +++ b/packages/alpinejs/src/alpine.js @@ -3,7 +3,7 @@ import { mapAttributes, directive, setPrefix as prefix, prefix as prefixed } fro import { start, addRootSelector, addInitSelector, closestRoot, findClosest, initTree, destroyTree, interceptInit } from './lifecycle' import { onElRemoved, onAttributeRemoved, onAttributesAdded, mutateDom, deferMutations, flushAndStopDeferringMutations, startObservingMutations, stopObservingMutations } from './mutation' import { mergeProxies, closestDataStack, addScopeToNode, scope as $data } from './scope' -import { setEvaluator, evaluate, evaluateLater, dontAutoEvaluateFunctions, runIfTypeOfFunction } from './evaluator' +import { setEvaluator, evaluate, evaluateLater } from './evaluator' import { transition } from './directives/x-transition' import { clone, cloneNode, skipDuringClone, onlyDuringClone, interceptClone } from './clone' import { injectMagics, magic } from './magics' @@ -27,12 +27,10 @@ let Alpine = { get raw() { return raw }, version: ALPINE_VERSION, flushAndStopDeferringMutations, - dontAutoEvaluateFunctions, disableEffectScheduling, startObservingMutations, stopObservingMutations, setReactivityEngine, - runIfTypeOfFunction, onAttributeRemoved, onAttributesAdded, closestDataStack, diff --git a/packages/alpinejs/src/evaluator.js b/packages/alpinejs/src/evaluator.js index 6c662dad7..88a3d2f3c 100644 --- a/packages/alpinejs/src/evaluator.js +++ b/packages/alpinejs/src/evaluator.js @@ -2,20 +2,6 @@ import { closestDataStack, mergeProxies } from './scope' import { injectMagics } from './magics' import { tryCatch, handleError } from './utils/error' -let shouldAutoEvaluateFunctions = true - -export function dontAutoEvaluateFunctions(callback) { - let cache = shouldAutoEvaluateFunctions - - shouldAutoEvaluateFunctions = false - - let result = callback() - - shouldAutoEvaluateFunctions = cache - - return result -} - export function evaluate(el, expression, extras = {}) { let result @@ -49,10 +35,10 @@ export function normalEvaluator(el, expression) { } export function generateEvaluatorFromFunction(dataStack, func) { - return (receiver = () => {}, { scope = {}, params = [] } = {}) => { + return (receiver = () => {}, { scope = {}, params = [], autoEvaluateFunctions = true } = {}) => { let result = func.apply(mergeProxies([scope, ...dataStack]), params) - runIfTypeOfFunction(receiver, result) + runIfTypeOfFunction(autoEvaluateFunctions, receiver, result) } } @@ -103,7 +89,7 @@ function generateFunctionFromString(expression, el) { function generateEvaluatorFromString(dataStack, expression, el) { let func = generateFunctionFromString(expression, el) - return (receiver = () => {}, { scope = {}, params = [] } = {}) => { + return (receiver = () => {}, { scope = {}, params = [], autoEvaluateFunctions = true } = {}) => { func.result = undefined func.finished = false @@ -117,7 +103,7 @@ function generateEvaluatorFromString(dataStack, expression, el) { // Check if the function ran synchronously, if (func.finished) { // Return the immediate result. - runIfTypeOfFunction(receiver, func.result, completeScope, params, el) + runIfTypeOfFunction(autoEvaluateFunctions, receiver, func.result, completeScope, params, el) // Once the function has run, we clear func.result so we don't create // memory leaks. func is stored in the evaluatorMemo and every time // it runs, it assigns the evaluated expression to result which could @@ -126,7 +112,7 @@ function generateEvaluatorFromString(dataStack, expression, el) { } else { // If not, return the result when the promise resolves. promise.then(result => { - runIfTypeOfFunction(receiver, result, completeScope, params, el) + runIfTypeOfFunction(autoEvaluateFunctions, receiver, result, completeScope, params, el) }).catch( error => handleError( error, el, expression ) ) .finally( () => func.result = undefined ) } @@ -134,12 +120,12 @@ function generateEvaluatorFromString(dataStack, expression, el) { } } -export function runIfTypeOfFunction(receiver, value, scope, params, el) { - if (shouldAutoEvaluateFunctions && typeof value === 'function') { +export function runIfTypeOfFunction(autoEvaluateFunctions, receiver, value, scope, params, el) { + if (autoEvaluateFunctions && typeof value === 'function') { let result = value.apply(scope, params) if (result instanceof Promise) { - result.then(i => runIfTypeOfFunction(receiver, i, scope, params)).catch( error => handleError( error, el, value ) ) + result.then(i => runIfTypeOfFunction(autoEvaluateFunctions, receiver, i, scope, params)).catch( error => handleError( error, el, value ) ) } else { receiver(result) } diff --git a/packages/alpinejs/src/utils/bind.js b/packages/alpinejs/src/utils/bind.js index 302071475..ecf231b29 100644 --- a/packages/alpinejs/src/utils/bind.js +++ b/packages/alpinejs/src/utils/bind.js @@ -1,4 +1,4 @@ -import { dontAutoEvaluateFunctions, evaluate } from '../evaluator' +import { evaluate } from '../evaluator' import { reactive } from '../reactivity' import { setClasses } from './classes' import { setStyles } from './styles' @@ -180,9 +180,7 @@ export function extractProp(el, name, fallback, extract = true) { binding.extract = extract - return dontAutoEvaluateFunctions(() => { - return evaluate(el, binding.expression) - }) + return evaluate(el, binding.expression, { autoEvaluateFunctions: false }) } return getAttributeBinding(el, name, fallback) diff --git a/packages/csp/src/evaluator.js b/packages/csp/src/evaluator.js index c0f12be87..793f8ce00 100644 --- a/packages/csp/src/evaluator.js +++ b/packages/csp/src/evaluator.js @@ -25,7 +25,7 @@ function generateDataStack(el) { } function generateEvaluator(el, expression, dataStack) { - return (receiver = () => {}, { scope = {}, params = [] } = {}) => { + return (receiver = () => {}, { scope = {}, params = [], autoEvaluateFunctions = true } = {}) => { let completeScope = mergeProxies([scope, ...dataStack]) let evaluatedExpression = expression.split('.').reduce( @@ -39,7 +39,7 @@ function generateEvaluator(el, expression, dataStack) { completeScope, ); - runIfTypeOfFunction(receiver, evaluatedExpression, completeScope, params) + runIfTypeOfFunction(autoEvaluateFunctions, receiver, evaluatedExpression, completeScope, params) } } diff --git a/packages/mask/src/index.js b/packages/mask/src/index.js index 2769fc3b5..684e04a6c 100644 --- a/packages/mask/src/index.js +++ b/packages/mask/src/index.js @@ -16,14 +16,15 @@ export default function (Alpine) { // We need to prevent "auto-evaluation" of functions like // x-on expressions do so that we can use them as mask functions. - Alpine.dontAutoEvaluateFunctions(() => { - evaluator(value => { - result = typeof value === 'function' ? value(input) : value - }, { scope: { + evaluator(value => { + result = typeof value === 'function' ? value(input) : value + }, { + scope: { // These are "magics" we'll make available to the x-mask:function: '$input': input, '$money': formatMoney.bind({ el }), - }}) + }, + autoEvaluateFunctions: false }) return result diff --git a/packages/sort/src/index.js b/packages/sort/src/index.js index fccc7382e..e115d42ec 100644 --- a/packages/sort/src/index.js +++ b/packages/sort/src/index.js @@ -49,21 +49,22 @@ function generateSortHandler(expression, evaluateLater) { return (key, position) => { // In the case of `x-sort="handleSort"`, let us call it manually... - Alpine.dontAutoEvaluateFunctions(() => { - handle( - // If a function is returned, call it with the key/position params... - received => { - if (typeof received === 'function') received(key, position) - }, - // Provide $key and $position to the scope in case they want to call their own function... - { scope: { + handle( + // If a function is returned, call it with the key/position params... + received => { + if (typeof received === 'function') received(key, position) + }, + // Provide $key and $position to the scope in case they want to call their own function... + { + scope: { // Supporting both `$item` AND `$key` ($key for BC)... $key: key, $item: key, $position: position, - } }, - ) - }) + }, + autoEvaluateFunctions: false + }, + ) } } From 970211ab00d6b6e8e6ca09afd26f9c94c4ba80c2 Mon Sep 17 00:00:00 2001 From: Chris Vilches Date: Mon, 22 Jul 2024 20:43:36 +0900 Subject: [PATCH 4/4] Renamed runIfTypeOfFunction to handleEvalResult --- packages/alpinejs/src/evaluator.js | 24 ++++++++++-------------- packages/csp/src/evaluator.js | 4 ++-- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/alpinejs/src/evaluator.js b/packages/alpinejs/src/evaluator.js index 88a3d2f3c..41faed6ee 100644 --- a/packages/alpinejs/src/evaluator.js +++ b/packages/alpinejs/src/evaluator.js @@ -38,7 +38,7 @@ export function generateEvaluatorFromFunction(dataStack, func) { return (receiver = () => {}, { scope = {}, params = [], autoEvaluateFunctions = true } = {}) => { let result = func.apply(mergeProxies([scope, ...dataStack]), params) - runIfTypeOfFunction(autoEvaluateFunctions, receiver, result) + handleEvalResult(autoEvaluateFunctions, receiver, result) } } @@ -103,7 +103,7 @@ function generateEvaluatorFromString(dataStack, expression, el) { // Check if the function ran synchronously, if (func.finished) { // Return the immediate result. - runIfTypeOfFunction(autoEvaluateFunctions, receiver, func.result, completeScope, params, el) + handleEvalResult(autoEvaluateFunctions, receiver, func.result, completeScope, params, el) // Once the function has run, we clear func.result so we don't create // memory leaks. func is stored in the evaluatorMemo and every time // it runs, it assigns the evaluated expression to result which could @@ -112,7 +112,7 @@ function generateEvaluatorFromString(dataStack, expression, el) { } else { // If not, return the result when the promise resolves. promise.then(result => { - runIfTypeOfFunction(autoEvaluateFunctions, receiver, result, completeScope, params, el) + handleEvalResult(autoEvaluateFunctions, receiver, result, completeScope, params, el) }).catch( error => handleError( error, el, expression ) ) .finally( () => func.result = undefined ) } @@ -120,18 +120,14 @@ function generateEvaluatorFromString(dataStack, expression, el) { } } -export function runIfTypeOfFunction(autoEvaluateFunctions, receiver, value, scope, params, el) { - if (autoEvaluateFunctions && typeof value === 'function') { - let result = value.apply(scope, params) +export function handleEvalResult(autoEvaluateFunctions, receiver, value, scope, params, el) { + const shouldCallFunc = autoEvaluateFunctions && typeof value === 'function' - if (result instanceof Promise) { - result.then(i => runIfTypeOfFunction(autoEvaluateFunctions, receiver, i, scope, params)).catch( error => handleError( error, el, value ) ) - } else { - receiver(result) - } - } else if (typeof value === 'object' && value instanceof Promise) { - value.then(i => receiver(i)) + const result = shouldCallFunc ? value.apply(scope, params) : value + + if (result instanceof Promise) { + result.then(i => receiver(i)).catch( error => handleError( error, el, value ) ) } else { - receiver(value) + receiver(result) } } diff --git a/packages/csp/src/evaluator.js b/packages/csp/src/evaluator.js index 793f8ce00..5555ebdee 100644 --- a/packages/csp/src/evaluator.js +++ b/packages/csp/src/evaluator.js @@ -1,4 +1,4 @@ -import { generateEvaluatorFromFunction, runIfTypeOfFunction } from 'alpinejs/src/evaluator' +import { generateEvaluatorFromFunction, handleEvalResult } from 'alpinejs/src/evaluator' import { closestDataStack, mergeProxies } from 'alpinejs/src/scope' import { tryCatch } from 'alpinejs/src/utils/error' import { injectMagics } from 'alpinejs/src/magics' @@ -39,7 +39,7 @@ function generateEvaluator(el, expression, dataStack) { completeScope, ); - runIfTypeOfFunction(autoEvaluateFunctions, receiver, evaluatedExpression, completeScope, params) + handleEvalResult(autoEvaluateFunctions, receiver, evaluatedExpression, completeScope, params) } }