feat(serialize, hash): add serialize to es-toolkit/util and hash to es-toolkit/util/hash - #2067
Merged
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
raon0211
force-pushed
the
feat/serialize
branch
from
August 30, 2026 04:17
2303e7e to
220bde3
Compare
deno publish type-checks node:crypto imports against @types/node, which is unavailable under Yarn PnP. Deno users can reach the subpath via npm:es-toolkit/util/hash, which resolves the conditional exports.
String keys in objects, Maps, and entries() collections are now always
quoted, so a string key can no longer collide with a number, boolean,
null, or symbol key (Map{'123':1} vs Map{123:1}), and keys containing
':' or ',' can no longer be confused with the surrounding structure.
The internal noQuotes flag is removed.
…tput
Every string embedded in the output is now consistently quoted:
Date('1970-01-01T00:00:00.000Z'), Symbol('a'), Error(TypeError: 'boom').
This distinguishes Symbol() from Symbol('') and keeps the Error
name/message boundary unambiguous. Invalid dates stay Date(null),
since null is not a string.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Adds two related utilities:
serialize(es-toolkit/util): serializes any value into a stable string.hash(es-toolkit/util/hash): SHA-256 + Base64URL hash of the serialized value — a stable 43-character identifier for cache keys and change detection.serialize spec
Mapkeys, andSetvalues are sorted (code-unit order, locale-independent), so structurally equal values always serialize identically regardless of insertion order.Date('...'),Symbol('a'),Error(Name: 'message')). String keys are always quoted ({'a':1},Map{'a':1}), so a string key never collides with a number/boolean/null key (Map{'123':1}vsMap{123:1}) and keys containing:or,cannot be confused with the surrounding structure.'str'(single quotes),-0→0,123n,Symbol('desc')(Symbol()without a description),NaN/Infinityas-is.Date('ISO')(invalid dates →Date(null)),RegExp(/.../flags),Set[...],Map{'k':v}, all typed arrays (BigInt64Arraywithnsuffixes),ArrayBuffer[bytes],Error(Name: 'message').Name{k:v}, honoringtoJSON(); objects withentries()(FormData,URLSearchParams,Headers) asTag{k:v}.#ref{n}back-references by visit order, with memoization for repeated references.Promise,WeakMap,Blob,DataView, boxed primitives, generators): throwTypeError.name:sourcewith newlines collapsed; native functions asname:[native].Dispatch uses fast predicates (
Array.isArray,isPlainObject,instanceof-based es-toolkit predicates) instead ofObject.prototype.toStringstring dispatch. Not designed for security purposes: strings and keys are not escaped.hash design
node/defaultconditions):crypto.hash('sha256', data, 'base64url')— requires Node.js 20.12+ (browser-support docs updated from 18+).node:cryptowith fixed vectors, padding block boundaries, multi-byte UTF-8, lone surrogates, 1MB input, and fast-check fuzzing.hashis reachable only via the explicites-toolkit/util/hashsubpath, so it never adds to bundles of the main entrypoints. Enforced in two layers:no-restricted-importsforbids anysrc/**file (outsidesrc/util/hash) from importing it.dist/util/hashreferences it, and that loadinges-toolkit/es-toolkit/utilat runtime loads no module underdist/util/hash. This runs in the existingyarn teststep of the Release workflow, gating every publish.jsr.jsonexports./util/hashto the node implementation (JSR has no conditional exports;crypto.hashverified working on Deno 2.x).exportsget autil/hash.jsshim (same pattern asfp/iterator).Benchmarks
vitest benchon Node.js 24 (Apple Silicon):serializealone vs the equivalent in ohash: 1.19x–1.34x faster across the same payloads. Benchmark files are included underbenchmarks/performance/.Structure
Every module has a colocated
.spec.ts. Docs added in all 4 languages for both functions.Checklist
yarn lint,tsc --noEmitcleanyarn buildverified: conditional dist outputs, isolation, runtime parity of both implementations