NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #79 most downloaded on npm
Tiny JavaScript tokenizer.
Last release 10 months ago
08 Dec 2025
Ships fairly regularly
a new release about every 10 months
Nearly every release is documented
notes for 25 of 25 stable releases
Nothing withdrawn
no release was ever pulled
13 years old
25 releases · first in 2014
Changed: js-tokens is now an ESM package! This means that it has "type": "module" (instead of "type": "commonjs") in package.json, and export default
"type": "module" (instead of "type": "commonjs") in package.json, and export default jsTokens in the JavaScript code (instead of module.exports = jsTokens). If you were already using ESM, this probably won’t make any difference for you. For CommonJS users, const jsTokens = require("js-tokens") should still work if you use Node.js 20.19.0 or later (which support require(esm)). Thanks to fisker Cheung (@fisker)!Fixed: /a[/]/ is now parsed as a RegularExpressionLiteral again (regression from 8.0.3). Thanks to No Two (@noootwo) for reporting!
/a[/]/ is now parsed as a RegularExpressionLiteral again (regression from 8.0.3). Thanks to No Two (@noootwo) for reporting!One column per quarter.
Added: Support for ES2023: #! hashbang comments at the start of files.
#! hashbang comments at the start of files.Fixed: Extremely long string literals, template literals, regex literals, identifiers, comments, and runs of whitespace are now supported where possib
Maximum call stack size exceeded or similar error. There are still a few [even more extreme such edge cases][known-failures], which I don’t think can be solved but are documented at least.Note: This requires "esModuleInterop": true in your tsconfig.json, but as far as I can tell that’s not a breaking change, since importing js-tokens wi…
export default, but apparently export = is the correct syntax to use for packages that export a single function, which can be used both in CJS and MJS. (Read more about [Incorrect default export]). It should now be possible to do const jsTokens = require("js-tokens") in a @ts-checkeded JS file without TypeScript complaining. Note: This requires "esModuleInterop": true in your tsconfig.json, but as far as I can tell that’s not a breaking change, since importing js-tokens with "esModuleInterop": false didn’t work at runtime anyway.Fixed: /]/ is now parsed as a RegularExpressionLiteral. That’s invalid regex syntax, unless [Annex B: Additional ECMAScript Features for Web Browsers]
/]/ is now parsed as a RegularExpressionLiteral. That’s invalid regex syntax, unless [Annex B: Additional ECMAScript Features for Web Browsers][annexb] is honored, which js-tokens does. Thanks to Jared Hughes (@jared-hughes) for reporting and fixing!Added: Support for the d regex flag.
Support for ES2022!
Added: Support for the d regex flag.
Added: A new token type – PrivateIdentifier – for things like #name.
this.#name now tokenizes differently:
IdentifierName: this, Punctuator: ., Invalid: #, IdentifierName: nameIdentifierName: this, Punctuator: ., PrivateIdentifier: #nameAdded: Support for ES2021: The ||=, &&= and ??= operators, as well as underscores in numeric literals (1_000).
||=, &&= and ??= operators, as well as underscores in numeric literals (1_000).Changed: The main export of this module is no longer a regex (accompanied by a small helper function). Instead, the only export is a function that tok
.default when using CommonJS: const jsTokens = require("js-tokens"). (import jsTokens from "js-tokens" also works in module environments.)jsTokens("<p>Hello, world!</p>", { jsx: true }).5n.?. and ??.Added: Support for ES2019. The only change is that \u2028 and \u2029 are now allowed unescaped inside string literals.
\u2028 and \u2029 are now allowed unescaped inside string literals.These are the breaking changes:
s regex flag.matchToToken function now have a closed property. It is set to undefined for the tokens where “closed” doesn’t make sense. This means that all tokens objects have the same shape, which might improve performance.These are the breaking changes:
'/a/s'.match(jsTokens) no longer returns ['/', 'a', '/', 's'], but ['/a/s']. (There are of course other variations of this.)closed property could now behave differently.No code changes. Just updates to the readme.
Fixed: ES2015 unicode escapes with more than 6 hex digits are now matched correctly.
This release contains one breaking change, that should [improve performance in V8][v8-perf]:
This release contains one breaking change, that should improve performance in V8:
So how can you, as a JavaScript developer, ensure that your RegExps are fast? If you are not interested in hooking into RegExp internals, make sure that neither the RegExp instance, nor its prototype is modified in order to get the best performance:
var re = /./g; re.exec(""); // Fast path. re.new_property = "slow";
This module used to export a single regex, with .matchToToken bolted on, just like in the above example. This release changes the exports of the module to avoid this issue.
Before:
import jsTokens from "js-tokens";
// or:
var jsTokens = require("js-tokens");
var matchToToken = jsTokens.matchToToken;
After:
import jsTokens, { matchToToken } from "js-tokens";
// or:
var jsTokens = require("js-tokens").default;
var matchToToken = require("js-tokens").matchToToken;
These are the breaking changes:
** exponentiation operator.These are the breaking changes:
'**'.match(jsTokens) no longer returns ['*', '*'], but ['**'].'**='.match(jsTokens) no longer returns ['*', '*='], but ['**='].Improved: Made the regex ever so slightly smaller.
Improved: Limited npm package contents for a smaller download. Thanks to @zertosh!
Fixed: Declared an undeclared variable.
Changed: Merged the 'operator' and 'punctuation' types into 'punctuator'. That type is now equivalent to the Punctuator token in the ECMAScript specif
- followed by a number is now correctly matched as a punctuator followed by a number. It used to be matched as just a number, but there is no such thing as negative number literals. (Possibly backwards-incompatible change.)Added: Support for the regex u flag.
u flag.Improved: jsTokens.matchToToken performance.
jsTokens.matchToToken performance.Fixed: Support for unicode spaces. They used to be allowed in names (which is very confusing), and some unicode newlines were wrongly allowed in strin
Changed: The jsTokens.names array has been replaced with the jsTokens.matchToToken function. The capturing groups of jsTokens are no longer part of th
jsTokens.names array has been replaced with the jsTokens.matchToToken function. The capturing groups of jsTokens are no longer part of the public API; instead use said function. See this gist for an example. (Backwards-incompatible change.)Changed: Match ES6 function arrows (=>) as an operator, instead of its own category (“functionArrow”), for simplicity. (Backwards-incompatible change.
=>) as an operator, instead of its own category (“functionArrow”), for simplicity. (Backwards-incompatible change.)...) are now matched as an operator (instead of three punctuations). (Backwards-incompatible change.)[annexb]: https://tc39.es/ecma262/#sec-additional-ecmascript-features-for-web-browsers [edge-cases]: https://github.com/lydell/js-tokens/blob/0db8dbbf
Your coding agent can read these notes before it upgrades. Set up the MCP server →