serialize-javascript: JSON.stringify with regexps, dates and functions
Serialize JavaScript to a superset of JSON that includes regular expressions and functions.
At a glance
- What is it?
- Yahoo's serialize-javascript emits literal JavaScript instead of JSON, so regexps, dates, Maps, Sets and some functions survive the trip from server to browser. It is a small single-export package, and its own README warns where that trick stops working.
- Who is it for?
- Adopt serialize-javascript when a server needs to hand literal JavaScript values, regexps, dates, Maps, Sets or self-contained functions, to a page or a .js file, and when the HTML escaping of </script> matters to you. Do not adopt it as a general worker-thread transport: the README states that passing arbitrary functions between workers is not possible, because closed-over variables and imports are lost.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 2, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap serialize-javascript fills between JSON.stringify and JavaScript
JSON.stringify handles strings, numbers, booleans, null, arrays and plain objects. It drops or mangles everything else. A function disappears from the output. A Date becomes an ISO string, so the value comes back as a string on the other side. A RegExp becomes an empty object. A Map or Set becomes an empty object too. If your server holds route definitions as regexps and your client-side router needs the same patterns, or your page needs a Date object rather than a date string, JSON.stringify is the wrong tool and there is no option flag that fixes it.
serialize-javascript targets that gap. Its single export returns literal JavaScript, not JSON, so the output can be saved as a .js file or dropped into a script element. The README names the origin of the code: it started as an internal module inside express-state and was later published as an independent npm package. The intended audience is therefore server-side JavaScript that renders or ships values to a browser, which is why the escaping behaviour described below is treated as a primary feature rather than a detail.
What the serializer emits, value by value
The README's usage example passes one object containing a string, a number, a nested object, an array, a boolean, null, undefined, Infinity, a Date, a Map, a Set, a named function, a regexp, a BigInt and a URL. The output is a single-quoted JavaScript string whose contents are an object literal. Reading that output tells you the mechanism: each value type gets its own emission rule. undefined stays the bare identifier undefined. Infinity stays the bare identifier Infinity. The Date is written as new Date("2016-04-28T22:02:17.000Z"). The Map becomes new Map([["hello","world"]]). The Set becomes new Set([123,456]). The function is written out as its own source text. The regexp becomes new RegExp("([^\\\\s]+)", "g"). The BigInt becomes BigInt("10") and the URL becomes new URL("https://example.com/").
Two consequences follow. First, the output is only meaningful to a JavaScript engine: it is an expression, not a data format, and any consumer that is not JavaScript cannot parse it. Second, deserialization is evaluation. The README states plainly that deserializing is not part of the module and suggests writing it yourself with eval('(' + serializedJavascript + ')'), noting the parentheses are required because a leading brace would otherwise be read as a block. That is a deliberate boundary: the package produces a string and takes no position on how you turn it back into values.
HTML escaping, the unsafe flag, and why </script> is the test case
The README calls automatic escaping of HTML characters a primary feature. The example is direct: serialize an object whose only property is the string '</script>', and the returned string contains \\u003C\\u002Fscript\\u003E instead of the raw characters. That matters because the output is meant to be embedded in an HTML document; an unescaped closing script tag inside the payload would terminate the inline script element early and turn any user-controlled string into an injection point. JavaScript line terminators are escaped on the same pass.
Escaping is on by default and you have to opt out. Passing {unsafe: true} gives a straight conversion with no XSS protection, and the README says you will have to roll your own. There is a middle case worth noting: {isJSON: true} tells the serializer the payload contains no functions or regexps, which enables a path the README describes as over 3x faster, and the note attached to that option states the output is still escaped. So the fast path does not quietly disable the safety behaviour. If you are serializing a large pure-JSON payload into a page, isJSON is the option to reach for, and the escaping guarantee survives it.
Installing serialize-javascript and serializing a first object
The README gives one install command. Run it in the project that will do the serializing, which in most cases is the server, not the browser bundle.
npm install serialize-javascriptThe package has a single export, so requiring it and calling it is the whole API surface. This snippet mirrors the README's usage example at a smaller scale: a string, a date and a regexp, the three cases where JSON.stringify would lose information.
var serialize = require('serialize-javascript');
var out = serialize({
msg : 'hello',
date: new Date('Thu, 28 Apr 2016 22:02:17 GMT'),
re : /([^\s]+)/g
});
console.log(out);The value printed to the console is a JavaScript string whose contents are an object literal, with the date emitted as new Date(...) and the regexp emitted as new RegExp(...). To embed it in a page, write that string inside a script element; the README states that HTML characters and line terminators are escaped automatically so the payload cannot close the element. If you want readable output while inspecting it, pass the options object with space set to a number of spaces:
serialize(obj, {space: 2});There is no deserialize export. If you need to read the string back, the README's suggested helper is eval('(' + serializedJavascript + ')'), with the parentheses included because the opening brace would otherwise start a block. Treat that as a decision point rather than a copy-paste step: you are choosing to evaluate a string.
Where serialize-javascript breaks: closures, imports and worker threads
The README carries an explicit warning against using the package to move functions into worker threads. The reasoning is worth quoting in substance: a serialized function runs properly only if it is entirely self-contained. If the function body references a closed-over variable, or an import from another package, the serialized copy has no way to resolve it on the other side. The README's conclusion is blunt: it is not possible in general to send arbitrary JavaScript to a worker thread and have it behave as it did on the main thread, and this package does not let you do that.
The failure mode is quiet. A function that closes over a config object serializes without error and produces plausible source text; the error appears later, at call time, when the missing reference throws or resolves to something unintended. The same class of problem applies to any function whose behaviour depends on module scope.
There is a second, smaller constraint in the README: serializing ES6 Sets and Maps requires Array.from, which the README notes is unavailable in IE and in Node older than 0.12, or an Array.from polyfill. The package.json engines field is stricter than that historical note: it declares node >=20.0.0. If you are targeting a runtime below that, the engines field is the number to check first, not the polyfill aside.
How serialize-javascript differs from JSON.stringify and from structuredClone
The nearest alternative is JSON.stringify itself, and the difference is the return type rather than the feature list. JSON.stringify returns JSON, a data format any language can parse, and it loses functions, regexps, Maps and Sets while flattening Dates to strings. serialize-javascript returns JavaScript source, keeps those types by emitting constructor calls and function bodies, and in exchange produces something only a JavaScript engine can consume. If your payload crosses a language boundary, JSON.stringify is the right answer and serialize-javascript is not.
The other comparison is structuredClone, the platform's built-in structured clone algorithm. It handles Dates, Maps, Sets and cyclic references natively, but it does not carry functions or regexps as live values, and it produces an in-memory clone rather than a string you can write into a file or an HTML document. serialize-javascript exists for the case where the destination is text: a rendered page, a generated .js file, a script element. That is the axis to compare on. If you need a clone inside one process, structuredClone is simpler and needs no dependency. If you need text that a browser will evaluate, and that text must contain a regexp or a function, serialize-javascript is aimed at exactly that.
One more practical difference: the HTML escaping. JSON.stringify does not escape </script>, so embedding its output in a script element requires your own escaping step. serialize-javascript does it by default.
Maintenance, licence and the cost of upgrading serialize-javascript
The repository is not archived, and the last push was on 2026-09-23, one day before this article's reference point. Releases are frequent and small: v7.0.7 on 2026-06-30, v7.1.0 on 2026-08-08, v7.1.1 on 2026-08-29, with package.json at 7.1.2. The version history shows a 6.x to 7.x line, and the related searches people run include "serialize javascript 6.0 2" and "serialize javascript 7.0 3", which suggests major-version moves are the upgrade events users look up. The README does not document a migration path between major versions, so the changelog is the place to look before bumping, and the package's own test script is the check to run after.
npm testThat script runs node --test test/unit/*.js, and there is a separate benchmark script, node -v && node test/benchmark/serialize.js, if you want to compare the isJSON fast path against your own payloads. The dependency footprint is close to zero: the only devDependency is benchmark, and there are no runtime dependencies listed.
On licensing, the README says the software is free to use under the Yahoo! Inc. BSD license and points at the LICENSE file for the text and copyright. The package.json license field says BSD-3-Clause, while the repository metadata carries a NOASSERTION identifier, so the two sources do not agree on the label. If the exact terms matter to your organisation, read the LICENSE file rather than either metadata field. Nothing here is legal advice.
Editorial conclusion
Adopt serialize-javascript when a server needs to hand literal JavaScript values, regexps, dates, Maps, Sets or self-contained functions, to a page or a .js file, and when the HTML escaping of </script> matters to you. Do not adopt it as a general worker-thread transport: the README states that passing arbitrary functions between workers is not possible, because closed-over variables and imports are lost. Before wiring it in, check that your Node runtime satisfies the engines field (>=20.0.0), decide whether the isJSON fast path applies to your payload, and confirm whether you can accept the eval-based deserializer the README suggests, since no deserialize function ships with the package.
Frequently asked questions
What is serialize-javascript used for?
It serializes JavaScript values to a superset of JSON that includes regular expressions, dates and functions, returning literal JavaScript that can be saved to a .js file or embedded in an HTML script element. The README names client-side URL routing, where regexp route definitions are shared from server to client, as a motivating example.
How do I install serialize-javascript?
The README gives a single npm command, npm install serialize-javascript. The package.json engines field declares node >=20.0.0, so check your runtime before installing.
Does serialize-javascript escape HTML characters by default?
Yes. The README states that HTML characters and JavaScript line terminators are escaped automatically, and shows '</script>' coming out as \\u003C\\u002Fscript\\u003E. You can pass {unsafe: true} for a straight conversion without that protection.
Can serialize-javascript pass functions to worker threads?
The README warns against it. A serialized function must be entirely self-contained, and anything referencing a closed-over variable or an import from another package will not run properly after deserialization.
Does serialize-javascript include a deserialize function?
No. The README states that deserializing is explicitly not part of the module and suggests writing it yourself with eval('(' + serializedJavascript + ')'), noting the parentheses are needed because the opening brace would otherwise be treated as a block.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/yahoo-serialize-javascript)