Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ var PLACE_HOLDER_REGEXP = new RegExp('(\\\\)?"@__(F|R|D|M|S|A|U|I|B|L)-' + UID +
// call could start past a `[native code]` match and wrongly report a native
// function as safe to serialize.
var IS_NATIVE_CODE_REGEXP = /\{\s*\[native code\]\s*\}/;
var IS_PURE_FUNCTION = /function.*?\(/;
var IS_ARROW_FUNCTION = /.*?=>.*?/;
// Classify the outer function, not a declaration or arrow inside its body.
var IS_PURE_FUNCTION = /^(?:async(?:\s|\/\*[\s\S]*?\*\/|\/\/[^\n]*\n)+)?function\b/;
var IS_ARROW_FUNCTION = /^(?:async(?:\s|\/\*[\s\S]*?\*\/|\/\/[^\n]*\n)+)?(?:\([\s\S]*?\)|[^\s()]+)\s*=>/;
var UNSAFE_CHARS_REGEXP = /[<>\/\u2028\u2029]/g;
// Matches a script end tag (case-insensitive) for XSS protection: either a
// literal `</script>`, or a bare `</script` followed by one of the other
Expand Down
66 changes: 66 additions & 0 deletions test/unit/method-bodies.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
const { describe, it } = require('node:test');
const { strictEqual } = require('node:assert');
const serialize = require('../../');

describe('method bodies containing other functions', function () {
it('round trips a method containing an arrow with destructured parameters', function () {
const input = {
method() {
const nested = ({ value }) => value;
return nested({ value: 42 });
}
};
const output = eval('(' + serialize(input) + ')');
strictEqual(output.method(), 42);
});

it('round trips a method containing a function declaration', function () {
const input = {
method() {
function nested() { return 42; }
return nested();
}
};
const output = eval('(' + serialize(input) + ')');
strictEqual(output.method(), 42);
});

it('preserves async methods containing arrows', async function () {
const input = {
async method() {
const nested = () => 42;
return nested();
}
};
const output = eval('(' + serialize(input) + ')');
strictEqual(await output.method(), 42);
});

it('preserves generator methods containing arrows', function () {
const input = {
*method() {
const nested = () => 42;
yield nested();
}
};
const output = eval('(' + serialize(input) + ')');
strictEqual(output.method().next().value, 42);
});
});


describe('outer function signatures', function () {
it('preserves async signatures with comments instead of spaces', async function () {
for (const fn of [async/**/function () { return 42; }, async/**/() => 42]) {
const output = eval('(' + serialize(fn) + ')');
strictEqual(await output(), 42);
strictEqual(output.constructor.name, 'AsyncFunction');
}
});

it('preserves arrows whose default arguments contain functions', function () {
const fn = (callback = function () { return 42; }) => callback();
const output = eval('(' + serialize(fn) + ')');
strictEqual(output(), 42);
});
});