CHANGES:
Features/Changes
- Compiler: initial support for OCaml 5.5.0 (#2197, #2220)
- Compiler: OxCaml support (#2105, #2225)
- Compiler: new variable coalescing pass, plus faster variable-naming,
free-variable and shape-computation passes (#2166, #2321, #2198) - Compiler: add the
--build-configand--apply-build-configflags (#2177) - Compiler: put more values into global variables (#2211)
- Compiler: cosmetic minification in compact mode —
!0/!1booleans,
drop the leading0in0.xfractions, normalise exponents
(1e+05→1e5), and pick backtick strings when they reduce escapes;
--prettyoutput is unchanged (#1117) - Wasm: dynlink and toplevel support (#2186)
- Compiler/wasm: WASI 0.1 support (#1831)
- Wasm_of_ocaml: alternative effect implementation based on the Stack
Switching proposal (#2189) - Runtime/wasm: implement the legacy
numlibrarynatprimitives
(previously no-op stubs), so arbitrary-precision integers and rationals
now work as on the JavaScript runtime (#2263) - Runtime/wasm: faster string↔ArrayBuffer copies, faster small-string
conversions, and optimized bigstring primitives (#2124, #2144) - Runtime/wasm: pure-Wasm zstd and BLAKE2b implementations; the runtime
no longer relies on the JavaScript zstd/BLAKE2 shims to unmarshal
compressed values or compute Digest.BLAKE512/256/128. This also makes
both available under the WASI target, which has no JavaScript (#2249) - Runtime: initial support for quickjs-ng (#2229)
- Lib: add
Promise— type-safe bindings to JavaScript promises (even for
'a Promise.t Promise.t), with Lwt interop inJs_of_ocaml_lwt.Promise
(to_lwt/of_lwt) and Promise-typedDom_htmlbindings
(requestFullscreen,requestPointerLock,exitFullscreen,
mediaElement.play,imageElement.decode,Animation.{finished,ready}).
Breaking:mediaElement.playnow returnsunit Promise.t(#2031) - Lib: add
FetchandAbort— Fetch API binding with a typed
AbortController/AbortSignalprimitive for cancellation (#596) - Lib: many additional
Dom_htmlbindings and a newPerformancemodule
(#2221, #2248) - Lib: add
Consolebindings fortable,count,countResetand
timeLog(#2350) - Lib: align
Dom_svgwith SVG 2 — newgraphicsElement/geometryElement
parents,style/className/datasetmerged intoelement, SVG 2
members,markerElementand the fullSVGFE*filter-primitive family,
every SVG element is now an event target (#519), andprop/readonly_prop
fixes. Breaking: drops the SVG 1.1-onlygetTransformToElement;
nearestViewportElement/farthestViewportElementare now typedoptdef - Lib: implement the popover API (#1734)
- Lib: add
Intl.RelativeTimeFormat(#2070) - Lib: remove dead legacy-browser code from the DOM bindings (IE
attachEvent/createElement/cancelBubblefallbacks, prefixed
requestAnimationFrame, the Firefox 3.xFile.fileNameproperty).
Breaking: drops the obsolete GeckoMouseScrollEvent/_DOMMouseScroll
bindings — themouseScrollEventtype, theMouseScrollEvent
taggedEventvariant,CoerceTo.mouseScrollEventand
Event._DOMMouseScroll(#2350)
Bug fixes
- Compiler: don't rewrite
x = e + xintox += efor+(not
commutative on strings), which reversedFilename.concatoperands and
brokeFilename.temp_filein whole-program builds (#2228) - Compiler: fix the dead
require()guard in share_constant (it matched
"requires"), which could replacerequirestring arguments and confuse
bundlers (#2284) - Compiler: parenthesize
inin conditional else-branches, arrow concise
bodies andfor-initializer yields when re-printing parsed JavaScript,
which previously emitted output that did not parse (#2282) - Compiler: emit a flat dispatch loop instead of deeply nested labelled
blocks for many sibling merge targets, avoiding parser "too much
recursion" overflows (#2122) - Compiler: avoid JS stack overflow on deep mutually-recursive direct-style
calls under--effects=double-translation(#2243) - Compiler: fix reference unboxing (#2210), a missing conditional
simplification (#2217),Js_assign.simpl(#2218), and UGEINT lowering - Compiler/wasm: fix the int-division return type (#2197), preserve the
physical identity of empty closures (#2207), and fix a crash on some
function calls (#2208) - Runtime: hashing is now consistent across backends — JS strings with code
points above U+00FF mix two 16-bit units per word,Hashtbl.hashof float
arrays, bigarray tail zero-extension andfloat32_hashnormalize like
native; ASCII/Latin-1 strings are unchanged (#2263, #2270, #2332) - Runtime/wasm: bring many primitives in line with the JavaScript runtime —
caml_wrap_exceptiononly wraps realErrors,caml_js_meth_call
decodes method names as UTF-8, the exception formatter grows its buffer,
Sys.is_directory/file_existsfollow symlinks,isattyreturns false
in browsers,caml_seek_invalidates the destination,Array.make/
Obj.new_blockbuild proper float arrays,caml_unregister_named_value
handles non-head bucket entries, the lexer only moves position memory on
memory-action transitions, the bytecode-section accessors raise without
--toplevel, format-string#/%+f/% fcorner cases, and
Condition.waitis a no-op with each condition variable having a distinct
identity (#2263) - Runtime: marshalling fixes on both backends —
Marshal.to_bufferreturns
the byte count; float arrays useCODE_DOUBLE_ARRAY(readable by native
and Wasm); BLOCK32 sizes are decoded with an unsigned shift (≥ 2^21 fields
no longer truncated) and a block with ≥ 2^22 fields raises instead of
truncating;input_valueon a bad object raisesFailure; bigarray
deserialization rejects bad dimensions; big-endian double arrays are
registered in the object table (#2263, #2270) - Runtime: filesystem fixes (#2270) — the fake device no longer destroys a
directory renamed into its own subtree, refuses to unlink directories,
honorsOpen_append(which now implies write access), reports proper Unix
error codes/syscalls/paths, no longer matches mount points as regexes,
raisesSys_erroron cross-device renames, keeps file sizes 64-bit on the
node backend, and no longer deletes a file renamed onto itself;flushon
a closed channel no longer raises - Runtime:
O_APPEND/Open_appendmatches native on both backends — the
file offset starts at 0 (solseek/pos_outreport 0 right after opening)
and every write goes to the end of the file, even after seeking backwards
(#2306) - Runtime: an empty path raises
ENOENTon the JavaScript backend like
native (and the Wasm runtime), soUnix.stat "",Unix.opendir "", etc.
raise instead of operating on the cwd, andSys.file_exists ""is false
(#2354) - Runtime: Unix fixes —
Unix.localtimecomputestm_ydayfrom the date
(was off by one during DST) and reachesIntlsafely;Unix.closefrees
the fd-table slot;Unix.error_messageno longer crashes on unknown codes
or node < 22;chmodraisesUnix_error;readdirincludes "." and
"..", and addUnix.getegid/ fix theUnix.getgrgidexport (#2263,
#2270, #2303, #2304) - Runtime: channel fixes —
in_channel_of_descr/out_channel_of_descr
allocate fresh channels (they used to share a record and loop on reads);
refill-hook channels grow their buffer and keeppos_in/pos_out
correct;Sys.commandreturns the child exit status;Sys.getenvraises
on prototype names;Sys.isattyconsults the channel's file (#2270, #2330) - Runtime: Str engine fixes — SIMPLEOPT/STAR/PLUS no longer read past the
end of the string (a trailing negated class could loop forever),
instruction arguments are no longer masked to 8 bits (regexps with > 256
pool entries mis-indexed), and aStr.replacebackreference one past the
last group raises instead of trapping (#2263, #2270) - Runtime: ephemeron/weak fixes —
blit_key,blit_data,get_data,
get_copyandget_data_copycorrected (no clobbering, copy bytes and
float arrays, no traps on JS-valued data); data is weakly keyed on the key
object so key↔data cycles can be collected;Gc.finalise_lastruns under
--effects=cps;Gc.countersreturns a plain tuple (#2263, #2270, #2274,
#2279) - Runtime: numeric fixes —
Digest/MD5 correct for inputs ≥ 2 GiB;
Int64.shift_rightfor negatives with shift counts 41–47;
Int64.of_string(#2223);Printf "%#x" 0prints0; float16 bigarray
NaN comparison; comparing an immediate against a custom block no longer
throws and orders correctly;Float.Array.sub/append/concatreturn
tag-254 arrays;caml_bigstring_blit_*treat positions as raw offsets;
compare_natreads only the common digit length (#2263, #2270) - Runtime: float formatting and parsing — the exact decimal expansion is
printed beyondtoFixed/toExponential's limits (%.150e,%fof values
≥ 1e21); hex-float literals parse with correct rounding, saturate huge
exponents instead of wrapping, and reject non-decimal/JavaScript literals;
ldexprounds once into the subnormal range; andfloat_of_stringskips
all leading whitespace (#2263, #2270) - Runtime:
caml_float16_of_doublerounds throughfloat32like native, so
float16tie values agree across the js, wasm and native backends; and
Unix.getuid/geteuid/getgid/getegidreturn the real ids on Node (the
WASI build keeps1) (#2280) - Runtime: Graphics backend fixes (#2270) — consistent bottom-left pixel
origin across all primitives, correctdraw_arcquadrant, synchronous
firstdraw_image,fill_rectpaints the far edges, pie-slicefill_arc,
half-pixel-centred strokes/fills for crisp lines, and round caps/joins,
matching the native X11 backend - Runtime:
Domain.spawnof a raising body now succeeds andDomain.join
re-raises (with theFinishedpayload layout expected per OCaml version),
instead of corrupting the domain id and termination mutex (#2263, #2270,
#2302) - Runtime:
caml_dynlink_open_libdrops themodeargument on OCaml ≥ 5.1
and returns the filled library-slot index (#2270) - Runtime: misc runtime-review fixes —
Runtime_events.User.register
orderstyp/tagcorrectly and the cursor primitives are renamed
caml_ml_runtime_events_*;jsoo_effect_not_supportedis provided only
when effects are disabled;Blake2.createtruncates an over-long key;
OCAMLRUNPARAMbacktrace parsing is last-wins; fixcaml_oo_cache_id
(#2224) and JS→OCaml string conversion (#2230) (#2263, #2270) - Lib: binding fixes (#2350) —
CSS.Angleparses integer angles such as
"45deg";CSS.Colorrejects empty channels ("rgb(,,)");
IntersectionObserver.takeRecordsis wrapped inJs.t;EventSource
onopen/onerrorreceive a plainDom.event;Intl.Collator.compare
returnsJs.number_t;Dom.attr.ownerElementis typedelement t opt readonly_prop;Regexp.replace_firstpreserves all flags exceptg
(adds aflagsaccessor) - Lib: fix method-name mangling —
Typed_array._BYTES_PER_ELEMENT_,
WebGL._MAX_RENDERBUFFER_SIZE_andcanvasElement.toDataURL_compression
resolved to the wrong JavaScript identifiers (#2239) - Lib: defer
Intl.{Collator,DateTimeFormat,...}member lookups so the
module no longer throws at load time whenglobalThis.Intlis undefined
(#2229) - Lib: fix
onbeforeunloadbreaking navigation (#1436) — the
event_listenerreturn type is nowbool t optdef(undefinedmeans "no
opinion"), with newDom.listener/full_listenerand a typed
beforeUnloadEvent - Lib: fix several
Dom_htmlbindings (#2221) - Lib:
Deriving_Jsonnow round-trips non-finite floats — the writer emits
NaN/Infinity/-Infinity(matching the reader) instead of OCaml's
nan/inf/-inf, which the reader rejected (#2365) - Lib: drop a stray
console.logfired on every event in
Lwt_js_events.mousewheel(#2365) - Lib:
Lwt_fileread functions now fail the thread with an exception on a
read error or abort instead of raisingassert false(#2365) - Lib:
Lwt_xmlHttpRequestframecontent_xmlreturnsNonefor non-default
response types (text/json/blob/arraybuffer/document) instead of raising
assert false(#2365) - Lib:
Lwt_js_events.request_animation_frameis now cancellable — cancelling
the thread cancels the pending animation-frame callback (#2365)