Skip to content

Commit

Permalink
Revert to more conservative strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
calebporzio committed Mar 7, 2020
1 parent 56f1693 commit 4225cdc
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 10 deletions.
15 changes: 12 additions & 3 deletions dist/alpine.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/alpine.js.map

Large diffs are not rendered by default.

21 changes: 16 additions & 5 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,26 @@ export function debounce(func, wait) {
}

export function saferEval(expression, dataContext, additionalHelperVariables = {}) {
return (new Function(['$data', '$extras'], `var result; with($extras) { with($data) { result = ${expression} } }; return result`))(
dataContext, additionalHelperVariables
return (new Function(['$data', ...Object.keys(additionalHelperVariables)], `var result; with($data) { result = ${expression} }; return result`))(
dataContext, ...Object.values(additionalHelperVariables)
)
}

export function saferEvalNoReturn(expression, dataContext, additionalHelperVariables = {}) {
if (! expression) expression = 'undefined'
return (new Function(['$data', '$extras'], `with ($extras) { var result; with($data) { result = ${expression} }; if (typeof result === 'function') { if (typeof $event !== 'undefined') { result($event); } else { result(); } } };`))(
dataContext, 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 methodReference.call(dataContext, additionalHelperVariables['$event'])
}
}

return (new Function(['dataContext', ...Object.keys(additionalHelperVariables)], `with(dataContext) { ${expression} }`))(
dataContext, ...Object.values(additionalHelperVariables)
)
}

Expand Down
39 changes: 38 additions & 1 deletion test/on.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ test('event with colon', async () => {
await wait(() => { expect(document.querySelector('span').getAttribute('foo')).toEqual('baz') })
})


test('prevent default action when an event returns false', async () => {
window.confirm = jest.fn().mockImplementation(() => false)

Expand All @@ -372,3 +371,41 @@ test('prevent default action when an event returns false', async () => {

expect(document.querySelector('input').checked).toEqual(true)
})

test('allow method reference to be passed to listeners', async () => {
document.body.innerHTML = `
<div x-data="{ foo: 'bar', changeFoo() { this.foo = 'baz' } }">
<button x-on:click="changeFoo"></button>
<span x-text="foo"></span>
</div>
`

Alpine.start()

expect(document.querySelector('span').innerText).toEqual('bar')

document.querySelector('button').click()

await new Promise(resolve => setTimeout(resolve, 1))

expect(document.querySelector('span').innerText).toEqual('baz')
})

test('event instance is passed to method reference', async () => {
document.body.innerHTML = `
<div x-data="{ foo: 'bar', changeFoo(e) { this.foo = e.target.id } }">
<button x-on:click="changeFoo" id="baz"></button>
<span x-text="foo"></span>
</div>
`

Alpine.start()

expect(document.querySelector('span').innerText).toEqual('bar')

document.querySelector('button').click()

await new Promise(resolve => setTimeout(resolve, 1))

expect(document.querySelector('span').innerText).toEqual('baz')
})

0 comments on commit 4225cdc

Please sign in to comment.