Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(utils): serialize inline functions (#5051) #5580

Merged
merged 14 commits into from Apr 22, 2019
29 changes: 29 additions & 0 deletions packages/utils/src/serialize.js
@@ -1,7 +1,36 @@
import serialize from 'serialize-javascript'

function normalizeFunctions(obj) {
galvez marked this conversation as resolved.
Show resolved Hide resolved
if (typeof obj !== 'object' || Array.isArray(obj) || obj === null) {
return obj
}
for (const key in obj) {
if (key === '__proto__' || key === 'constructor') {
continue
}
const val = obj[key]
if (val !== null && typeof val === 'object' && !Array.isArray(obj)) {
obj[key] = normalizeFunctions(val)
}
if (typeof obj[key] === 'function') {
const asString = obj[key].toString()
const match = asString.match(/^([^{(]+)=>\s*(.*)/)
if (match) {
let functionBody = match[2].match(/^{?(\s*return\s+)?(.*?)}?$/)[2].trim()
pimlie marked this conversation as resolved.
Show resolved Hide resolved
if (!match[2].trim().match(/^{/)) {
functionBody = `return ${functionBody}`
}
// eslint-disable-next-line no-new-func
obj[key] = new Function(...match[1].split(',').map(arg => arg.trim()), functionBody)
}
}
}
return obj
}

export function serializeFunction(func) {
let open = false
func = normalizeFunctions(func)
return serialize(func)
.replace(serializeFunction.assignmentRE, (_, spaces) => {
return `${spaces}: function (`
Expand Down
22 changes: 22 additions & 0 deletions packages/utils/test/serialize.test.js
Expand Up @@ -22,6 +22,28 @@ describe('util: serialize', () => {
expect(serializeFunction(obj.fn)).toEqual('() => {}')
})

test('should serialize arrow function with ternary in parens', () => {
const obj = {
// eslint-disable-next-line arrow-parens
fn: foobar => (foobar ? 1 : 0)
}
expect(serializeFunction(obj.fn)).toEqual('foobar => foobar ? 1 : 0')
})

test('should serialize arrow function with single parameter', () => {
const obj = {
// eslint-disable-next-line arrow-parens
fn: foobar => {},
fn2: foobar => 1,
fn3: foobar => {
return 3
}
}
expect(serializeFunction(obj.fn)).toEqual('foobar => {}')
expect(serializeFunction(obj.fn2)).toEqual('foobar => 1')
expect(serializeFunction(obj.fn3)).toEqual('foobar => {\n return 3;\n }')
})

test('should not replace custom scripts', () => {
const obj = {
fn() {
Expand Down