Releases: ml-in-barcelona/server-reason-react
Release list
0.5.1
CHANGES:
- Require
quickjs >= 0.5.1 & < 0.6.0: globalJs.String.replaceByRe/unsafeReplaceBy*/splitByReoperations now prepare the regexp input once instead of copying and converting it for every match, making ordinary dense global replacements and splits linear in input plus output size. Replacement rendering writes source ranges directly without repeated UTF-16 rescans or eager prefix/suffix copies, callback replacements collect matches before invoking callbacks like JavaScript, and matches that split a surrogate pair produce U+FFFD rather than slicing the wrong UTF-8 bytes by @davesnx
0.5.0
CHANGES:
-
Fix hydration error #418 on subtrees optimized by the PPX (ahrefs guest site, WEB-844): the
React.Writer/React.Staticfast paths dropped the<!-- -->separators that react-dom emits between adjacent text nodes, so the browser merged them into one text node and React discarded the server HTML.renderToString/renderToStreamnow emit the separators through optimized subtrees (compile-time where both sides are known, threaded at runtime across dynamic holes),renderToStaticMarkupstays separator-free, and fully-static elements with adjacent text children demote to the Writer tier since the separator is mode-dependent by @davesnx -
Unify the synchronous renderers:
renderToString,renderToStaticMarkupand the Writer fast path now share one tree walker (render_tree) with threaded text-run state instead of two divergent copies with mutable flags. As a consequence, Suspense boundaries inside PPX-optimized subtrees keep their<!--$-->hydration markers (previously dropped),ReactDOM.write_to_bufferoutput is byte-identical torenderToStaticMarkup, and the sync renderers no longer emit a spurious text separator after aStatic/Writersibling.React.Writer'semitfield now takes~separators:boolandReactDOM.write_element_to_bufferis the new threaded entry point for generated code by @davesnx -
Fix PPX-generated
Writeremit bodies capturing user variables namedb(e.g.<div>{React.string(b)}</div>failed to compile): generated bindings now use reserved__buf/__separators/__prev_textnames by @davesnx -
Remove the dead
Html.rawchild extractor from the PPX static analysis (Html.rawchildren never typechecked asReact.element) by @davesnx -
Require
quickjs >= 0.5.0 & < 0.6.0:Js.ReandJs.Stringare built on quickjs 0.5.0's breaking API (RegExp.execreturnsmatch_result option, captures arestring option array, indices are UTF-16 code units) by @davesnx -
Complete
Js.Bigint's Melange-named API:asIntN/asUintN(labeled wrappers overas_int_n/as_uint_n),toLocaleString(plain decimal, no ICU) andmake(unsupported: needs JS runtime coercion) by @davesnx -
Fix
Belt*Exnexception types to match Melange:Belt.Option/List/Result/Map*/Set*/MutableMap*/MutableSet*/MutableQueuegetExn/headExn/tailExn/peekExn/popExnnow raiseNot_foundandBelt.Array.getExn/setExnraiseAssert_failure(previously all raisedJs.Exn.Errorwith a fake file path, so universaltry ... with Not_foundhandlers caught on the client but crashed on the server).Belt.Array.pushnow raises (with a compile-time alert) instead of silently returning a sentinel by @davesnx -
Rewrite
Js.Dictto preserve JS object key order: iteration (entries/keys/values) follows insertion order, duplicate keys infromList/fromArraycollapse (first position, last value) like JS object literals, andJs.Json.stringifyconsequently serializes objects in insertion order (previously Hashtbl bucket order with duplicates retained) by @davesnx -
Implement
Js.MapandJs.Setnatively (previously type-only stubs): full Melange 6 API with JS semantics — mutable, insertion-ordered iteration,fromArraydedup, chainableset/add. Key equality is structural instead of SameValueZero (documented) by @davesnx -
Add
Js.Iteratorand the modernJs.Arraymethods:at,findLast/findLasti/findLastIndex/findLastIndexi,flat,toReversed,toSortedWith,toSpliced,removeFrom,removeCount, andentries/keys/valuesiterators.toSorted(comparator-less) stays unsupported: JS's default comparator string-coerces elements by @davesnx -
Fix
Js.Float.toExponential/Js.Int.toExponentialwithout~digitsto return exponential notation with the shortest round-trip digits ((123456).toExponential()is now"1.23456e+5", previously"123456"), andJs.Float.toFixedof values ≥ 1e21 to fall back to exponential form like JS by @davesnx -
Fix
Js.Bigint.of_string/of_string_exnrejecting hex literals containinge/Edigits (BigInt("0xE0")is 224) by @davesnx -
Fix
Js.Promise.race [||]to return a forever-pending promise like JS (previously raised) by @davesnx -
Widen
Js.Consolesignatures to Melange's polymorphic API ('a -> unit); the functions remain silent no-ops on the server by @davesnx -
Port Melange's
Js.*test suites to native (js_array/js_dict/js_obj/js_global/js_int/js_float/js_promise_basic/js_re/js_string/js_datefrom melange 6.0.1-54jscomp/test, ~280 cases): every expectation is Melange's own JS-verified value. Three divergences were found and documented instead of blessed:Js.Int.toExponential/Js.Float.toExponentialwithout~digitsreturnNumber.prototype.toStringoutput instead of exponential form, andJs.Float.toFixedof values ≥ 1e21 prints positionally where JS switches to exponential by @davesnx -
Port Melange's
Belttest suites to native (bs_array/bs_list/bs_map/bs_map_set_dict/bs_set_int/bs_mutable_set/bs_queue/bs_stack/bs_sort/bs_hashmap/bs_hashset_int/bs_float/bs_intfrom melange 6.0.1-54, ~120 cases incl. the 1M-element map/set/sort stress blocks): zero behavioral divergences — the only deltas are the already-documented*Exnexception types andBelt.Array.pushno-op by @davesnx -
Remove
Js.VectorandJs.TypedArray2(removed upstream in Melange 6; both were raising stubs natively) by @davesnx -
Implement
Js.Jsonnatively (all 25 functions were raising stubs): a strict ECMA-404 parser (parseExnraisesJs.Exn.SyntaxError, duplicate keys keep the last, surrogate-pair\uescapes decode to UTF-8) and an ECMA-262JSON.stringifyserializer (numbers formatted via quickjsNumber::toString, NaN/Infinity asnull,stringifyWithSpaceclamps indentation to 10).testnarrows its first argument toJs.Json.t(no runtime type info natively);stringifyAny/serializeExn/deserializeUnsaferemain unsupported. Melange'sjs_json_test.mlsuite is ported by @davesnx -
Implement
Js.Mathnatively (45 of 59 members were raising stubs) with ECMA-262 semantics where they diverge from IEEE 754/OCaml defaults:max_float/min_floatpropagate NaN and order ±0,pow_floatreturns NaN for NaN exponents and±1 ** ±Infinity,roundrounds half towards +Infinity preserving -0,sign_floatpreserves signed zeros,froundrounds through binary32,clz32/imulwrap through int32, andrandomuses a lazily self-initialized PRNG state. Melange'sjs_math_test.mlsuite is ported by @davesnx -
Implement
Js.Globaltimers on Lwt:setTimeout/setInterval(+Floatvariants) schedule on the running Lwt event loop andclearTimeout/clearIntervalcancel, WHATWG/node-style. Callbacks only fire while an Lwt main loop is running (Dream,Lwt_main.run) by @davesnx -
Implement
Js.Exnaccessors:asJsExnmaps theJs.Exn.Error/EvalError/…/UriErrorexceptions to aJs.Exn.tcarryingnameandmessage(stack/fileNameareNonenatively);Js.Exn.tis now a concrete record instead of an empty abstract type by @davesnx -
Implement
Js.NullgetExn/map/bind/iter(labeled~f, raisingJs.Exn.Error "Js.Null.getExn"like Melange). The legacyJs.Null.test(removed upstream in Melange 6) is gone. Melange'sjs_null_test.mlsuite is ported by @davesnx -
Implement
Js.UndefinedgetExn/map/bind/iter(labeled~f, raisingJs.Exn.Error "Js.Undefined.getExn"like Melange). The legacyJs.Undefined.test(removed upstream in Melange 6) is gone;testAnystays unsupported (needs runtime type tags). Melange'sjs_undefined_test.mlsuite is ported by @davesnx -
Align
Js.Nullablewith Melange 6:map/bind/itertake a labeled~f— the previousbindhad a divergent'b t -> ('b -> 'b) -> 'b tsignature vs Melange'sf:('a -> 'b t) -> 'a t -> 'b t— plusisNullable/null/undefined(both represented asNonenatively). Melange'sjs_nullable_test.mlsuite is ported by @davesnx -
Implement the remaining
Js.Stringstubs:unsafeReplaceBy0-3(function-based regex replacement on the shared UTF-16 replace driver; non-participating capture groups are passed as""where JS passesundefined),anchor/link(ECMA-262 CreateHTML,"-escaping),localeCompare(byte-wise, no ICU collation), andtoLocaleLowerCase/toLocaleUpperCase(aliased to the locale-insensitive versions). OnlyJs.String.makestill raises (needs JSString()coercion) by @davesnx -
Add generated per-function compatibility READMEs for
JsandBelt(packages/Js/README.md,packages/Belt/README.md): a dune rule merges Melange 6's API surface, a mechanical scan for raising stubs, and hand-maintained divergence annotations, and fails the build when the annotations contradict the code. Statuses: verified-by-JS-sourced-tests / implemented-unverified / divergent / stub / missing by @davesnx -
Fix
ReactServerDOM.render_htmlcrashing on PPX-prerendered (Writer) subtrees that contain client components ("Client components can't be rendered via write_to_buffer") and duplicating hoistable elements (<title>/<meta>/<link>) contained inStaticprerendered subtrees: the RSC HTML path now rendersWritersubtrees via the regular walk (already performed for the model) and falls back to the walked HTML forStaticsubtrees whose walk hoisted something by @davesnx -
[esbuild-plugin] Fix client components failing to load in the browser when their chunk wasn't eagerly imported ("Lazy element type must resolve to a class or function"): the manifest registered components as
React.lazy, which the Flight client wrapped in a second lazy. The manifest now stores loader records andReactServerDOMEsbuildimplements the FlightpreloadModule/requireModulecontract (preload starts the import and blocks the module chunk; require returns the component synchronously) by @davesnx -
Demo: add JavaScript-identical
Js.String/Js.Date...
0.4.1
CHANGES:
- Use OCaml 5.4.0 by @davesnx in #335
- Use latest ppxlib by @davesnx in #334
- Update to latest quickjs by @davesnx
- Update dependency and usage by @davesnx in #333
- Add filter to esbuild plugin to scope entrypoint by @pedrobslisboa in #330
- Add back and forward navigation to nested router by @pedrobslisboa in #329
- Implement memo and memoCustomCompareProps by @davesnx
- Move Date, BigInt and modularise Js by @davesnx in #327
- Create complex navigation at RSC demo by @pedrobslisboa in #307
0.4.0
CHANGES:
- Add upper bound to quickjs 0.2.0
- Bump lwt to 5.9.2
- Expand styles prop into className and style props with optional handling by @pedrobslisboa in #324
- Lowercase components have ?key:string by @davesnx in #323
- Wrap client value on React.Upper_case_component by @pedrobslisboa in #322
- Fix remove last element on nested_modules by @pedrobslisboa in #321
- Add searchParams function to native URL by @pedrobslisboa in #320
- Add URL construct function and improve lib build by @EmileTrotignon in #317
- Specify model values at React by @pedrobslisboa in #309
- Allow async in client props by @pedrobslisboa in #315
- Improve the Fiber and Model stream context by @pedrobslisboa in #312
- Align Suspense with reason-react by @pedrobslisboa in #311
- Make client component to execute in runtime by @pedrobslisboa in #306
- Fix mismatch of the model and html on render_html by @pedrobslisboa in #305
- Fix createFromFetch interface and avoid transition on navigation by @davesnx in #299
- Change ppx execution order (styles expansion in server-reason-react) by @davesnx in #297
- Rename use function to usePromise in Experimental module by @pedrobslisboa in #298
- Add shared-folder-prefix arg to ppx by @davesnx in #294
0.3.1
0.3.0
CHANGES
- browser-ppx: process stritems by @jchavarri in #127
- Make React.Children.* APIs work as expected by @davesnx in #130
- Improve global crashes by @davesnx in #132
- Support assets in
mel.moduleby @jchavarri in #134 - browser_only: don't convert to runtime errors on identifiers or function application by @jchavarri in #138
- Port
jquoted strings interpolation from Melange by @jchavarri in #139 - mel.module: handle asset prefix by @jchavarri in #140
- Add browser_only transformation to useEffect automatically by @davesnx in #145
- Append doctype tag on html lowercase by @davesnx in #136
- Transform Pexp_function with browser_only by @davesnx in #146
Full Changelog: 0.2.0...0.3.0
0.2.0
CHANGES
- Remove data-reactroot attr from ReactDOM.renderToString #129 by @pedrobslisboa
- Make useUrl return the provided serverUrl #125 by @purefunctor
- Replace Js.Re implemenation from
pcreto quickjs b1a3e22 by @davesnx - Remove Belt.Array.push #122 by @davesnx
0.1.0
CHANGES
Initial release of server-reason-react, includes:
- Server-side rendering of ReasonReact components (renderToString, renderToStaticMarkup & renderToLwtStream)
server-reason-react.browser_ppxfor skipping code from the serverserver-reason-react.melange_ppxfor enabling melange bindings and extensions which run on the serverserver-reason-react.belta native Belt implementationserver-reason-react.jsa native Js implementation (unsafe and limited)server-reason-react.urlandserver-reason-react.url-nativea universal library with both implementations to work with URLs on the server and the clientserver-reason-react.promiseandserver-reason-react.promise-nativea universal library with both implementations to work with Promises on the server and the client. Based on https://github.com/aantron/promiseserver-reason-react.melange-fetcha fork of melange-fetch which is a melange library to fetch data on the client via the Fetch API. This fork is to be able to compile it on the server (not running).server-reason-react.webapia fork of melange-webapi which is a melange library to work with the Web API on the client. This fork is to be able to compile it on the server (not running).