What New TC39 Proposals Shaped JavaScript in the January 2024 Meeting?
The TC39 January 29 meeting reviewed progress of multiple proposals advancing to later stages—including Intl.DateTimeFormat.formatRange, JSON Modules, Private‑In, Class Static Initializer Block, ResizableArrayBuffer, new Intl APIs, RegExp enhancements, Array findLast, defer import, and several internationalization extensions—detailing requirements, implementations, and upcoming milestones.
TC39's January 29 meeting concluded with a review of proposals that achieved stage progress and recent changes.
Stage 3 → Stage 4
Advancing to Stage 4 requires:
Writing test262 tests for all proposal features.
At least two implementations passing the tests and shipping to production.
Submitting a pull request to integrate the proposal into the ECMAScript standard text, signed by an ECMA editor.
Intl.DateTimeFormat.prototype.formatRange
This proposal adds the ability to format date ranges for internationalization. It introduces two methods: Intl.DateTimeFormat.prototype.formatRange – returns a formatted string. Intl.DateTimeFormat.prototype.formatRangeToParts – returns an array of parts.
let date1 = new Date(Date.UTC(2007, 0, 10, 10, 0, 0));
let date2 = new Date(Date.UTC(2007, 0, 10, 11, 0, 0));
let fmt = new Intl.DateTimeFormat("en", { hour: "numeric", minute: "numeric" });
fmt.formatRange(date1, date2); // "10:00 – 11:00 AM"
fmt.formatRangeToParts(date1, date2); // [{type:'hour',value:'10',source:'startRange'}, …]Available in Chrome 79 and Node.js 12.9.0.
Stage 2 → Stage 3
JSON Modules
The proposal separates JSON Modules from Import Assertions, allowing modules to be imported as JSON with a type assertion.
import json from "./foo.json" assert { type: "json" };
import("foo.json", { assert: { type: "json" } });Modules must be valid JSON; otherwise, loading fails.
Private Fields In Operator
Introduces the in operator to test for the existence of private fields without triggering exceptions.
class C {
#brand;
#method() {}
static isC(obj) { return #brand in obj && #method in obj; }
}Stage 1 → Stage 2
Class Static Initializer Block
Allows static blocks inside classes that run during class evaluation and can access private fields.
export class C {
#x;
constructor(x) { this.#x = { data: x }; }
static { getX = obj => obj.#x; }
}
export function readXData(obj) { return getX(obj).data; }Other Proposals Discussed
ResizableArrayBuffer and GrowableSharedArrayBuffer
New buffer types that support efficient resizing and shared growth.
let rab = new ResizableArrayBuffer(1024, 1024**2);
assert(rab.byteLength === 1024);
rab.resize(rab.byteLength * 2);
assert(rab.byteLength === 2048);Intl.LocaleInfo
Provides locale‑specific information such as first day of week, weekend range, and text direction.
let zhHans = new Intl.Locale("zh-Hans");
zhHans.weekInfo; // {firstDay:1, weekendStart:6, weekendEnd:7, minimalDays:4}
zhHans.textInfo; // {direction:"ltr"}Intl.DisplayNames Extension
Expands DisplayNames to include months, weekdays, units, time zones, calendars, and numbering systems.
let dn = new Intl.DisplayNames("zh-Hans", {type:"month", style:"long"});
dn.of(1); // "1月"RegExp Set Notation
Adds set operations (intersection, difference) to regular‑expression character classes.
[A--B] // difference
[A&&B] // intersection
[\p{Decimal_Number}--[0-9]] // non‑ASCII digitsRegExp.escape
Introduces a utility to escape all RegExp meta‑characters.
RegExp.escape("Buy it. use it. break it. fix it."); // "Buy it\. use it\. break it\. fix it\."Array.prototype.findLast / findLastIndex
New array methods that search from the end of the array.
const arr = [{value:1},{value:2},{value:3},{value:4}];
arr.findLast(n => n.value % 2 === 1); // {value:3}
arr.findLastIndex(n => n.value % 2 === 1); // 2Defer Module Import Eval
Syntax to mark import statements as lazily initialized without propagating async/await.
import {x} from "y" with { lazyInit: true };Extend TimeZoneName Option
Adds additional formatting styles for time‑zone names in Intl.DateTimeFormat.
let options = ["short","long","shortGMT","longGMT","shortWall","longWall"];
options.forEach(name => console.log(new Date().toLocaleTimeString("zh-Hans", {timeZoneName:name})));EraDisplay
New option to control era formatting (never, always, auto).
new Intl.DateTimeFormat("zh-Hans").format(new Date(-752,3,13)); // "753/4/13" → "公元前 753/4/13 BC"Intl.LocaleMatcher
Exposes locale‑matching algorithm as a JavaScript API.
Intl.LocaleMatcher.match(["zh-Hans","en"], ["zh","en"], "en"); // "zh"The meeting also highlighted the formation of the JavaScript Chinese Interest Group (JSCIG), which aims to represent Chinese developers in TC39 discussions and promote ECMAScript improvements.
https://github.com/JSCIG/es-discuss/discussions
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
