Skip to content

Releases: ml-in-barcelona/server-reason-react

0.5.1

Choose a tag to compare

@davesnx davesnx released this 22 Jul 17:02

CHANGES:

  • Require quickjs >= 0.5.1 & < 0.6.0: global Js.String.replaceByRe/unsafeReplaceBy*/splitByRe operations 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

Choose a tag to compare

@davesnx davesnx released this 21 Jul 13:23

CHANGES:

  • Fix hydration error #418 on subtrees optimized by the PPX (ahrefs guest site, WEB-844): the React.Writer/React.Static fast 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/renderToStream now emit the separators through optimized subtrees (compile-time where both sides are known, threaded at runtime across dynamic holes), renderToStaticMarkup stays 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, renderToStaticMarkup and 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_buffer output is byte-identical to renderToStaticMarkup, and the sync renderers no longer emit a spurious text separator after a Static/Writer sibling. React.Writer's emit field now takes ~separators:bool and ReactDOM.write_element_to_buffer is the new threaded entry point for generated code by @davesnx

  • Fix PPX-generated Writer emit bodies capturing user variables named b (e.g. <div>{React.string(b)}</div> failed to compile): generated bindings now use reserved __buf/__separators/__prev_text names by @davesnx

  • Remove the dead Html.raw child extractor from the PPX static analysis (Html.raw children never typechecked as React.element) by @davesnx

  • Require quickjs >= 0.5.0 & < 0.6.0: Js.Re and Js.String are built on quickjs 0.5.0's breaking API (RegExp.exec returns match_result option, captures are string option array, indices are UTF-16 code units) by @davesnx

  • Complete Js.Bigint's Melange-named API: asIntN/asUintN (labeled wrappers over as_int_n/as_uint_n), toLocaleString (plain decimal, no ICU) and make (unsupported: needs JS runtime coercion) by @davesnx

  • Fix Belt *Exn exception types to match Melange: Belt.Option/List/Result/Map*/Set*/MutableMap*/MutableSet*/MutableQueue getExn/headExn/tailExn/peekExn/popExn now raise Not_found and Belt.Array.getExn/setExn raise Assert_failure (previously all raised Js.Exn.Error with a fake file path, so universal try ... with Not_found handlers caught on the client but crashed on the server). Belt.Array.push now raises (with a compile-time alert) instead of silently returning a sentinel by @davesnx

  • Rewrite Js.Dict to preserve JS object key order: iteration (entries/keys/values) follows insertion order, duplicate keys in fromList/fromArray collapse (first position, last value) like JS object literals, and Js.Json.stringify consequently serializes objects in insertion order (previously Hashtbl bucket order with duplicates retained) by @davesnx

  • Implement Js.Map and Js.Set natively (previously type-only stubs): full Melange 6 API with JS semantics — mutable, insertion-ordered iteration, fromArray dedup, chainable set/add. Key equality is structural instead of SameValueZero (documented) by @davesnx

  • Add Js.Iterator and the modern Js.Array methods: at, findLast/findLasti/findLastIndex/findLastIndexi, flat, toReversed, toSortedWith, toSpliced, removeFrom, removeCount, and entries/keys/values iterators. toSorted (comparator-less) stays unsupported: JS's default comparator string-coerces elements by @davesnx

  • Fix Js.Float.toExponential/Js.Int.toExponential without ~digits to return exponential notation with the shortest round-trip digits ((123456).toExponential() is now "1.23456e+5", previously "123456"), and Js.Float.toFixed of values ≥ 1e21 to fall back to exponential form like JS by @davesnx

  • Fix Js.Bigint.of_string/of_string_exn rejecting hex literals containing e/E digits (BigInt("0xE0") is 224) by @davesnx

  • Fix Js.Promise.race [||] to return a forever-pending promise like JS (previously raised) by @davesnx

  • Widen Js.Console signatures 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_date from melange 6.0.1-54 jscomp/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.toExponential without ~digits return Number.prototype.toString output instead of exponential form, and Js.Float.toFixed of values ≥ 1e21 prints positionally where JS switches to exponential by @davesnx

  • Port Melange's Belt test 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_int from 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 *Exn exception types and Belt.Array.push no-op by @davesnx

  • Remove Js.Vector and Js.TypedArray2 (removed upstream in Melange 6; both were raising stubs natively) by @davesnx

  • Implement Js.Json natively (all 25 functions were raising stubs): a strict ECMA-404 parser (parseExn raises Js.Exn.SyntaxError, duplicate keys keep the last, surrogate-pair \u escapes decode to UTF-8) and an ECMA-262 JSON.stringify serializer (numbers formatted via quickjs Number::toString, NaN/Infinity as null, stringifyWithSpace clamps indentation to 10). test narrows its first argument to Js.Json.t (no runtime type info natively); stringifyAny/serializeExn/deserializeUnsafe remain unsupported. Melange's js_json_test.ml suite is ported by @davesnx

  • Implement Js.Math natively (45 of 59 members were raising stubs) with ECMA-262 semantics where they diverge from IEEE 754/OCaml defaults: max_float/min_float propagate NaN and order ±0, pow_float returns NaN for NaN exponents and ±1 ** ±Infinity, round rounds half towards +Infinity preserving -0, sign_float preserves signed zeros, fround rounds through binary32, clz32/imul wrap through int32, and random uses a lazily self-initialized PRNG state. Melange's js_math_test.ml suite is ported by @davesnx

  • Implement Js.Global timers on Lwt: setTimeout/setInterval (+Float variants) schedule on the running Lwt event loop and clearTimeout/clearInterval cancel, WHATWG/node-style. Callbacks only fire while an Lwt main loop is running (Dream, Lwt_main.run) by @davesnx

  • Implement Js.Exn accessors: asJsExn maps the Js.Exn.Error/EvalError/…/UriError exceptions to a Js.Exn.t carrying name and message (stack/fileName are None natively); Js.Exn.t is now a concrete record instead of an empty abstract type by @davesnx

  • Implement Js.Null getExn/map/bind/iter (labeled ~f, raising Js.Exn.Error "Js.Null.getExn" like Melange). The legacy Js.Null.test (removed upstream in Melange 6) is gone. Melange's js_null_test.ml suite is ported by @davesnx

  • Implement Js.Undefined getExn/map/bind/iter (labeled ~f, raising Js.Exn.Error "Js.Undefined.getExn" like Melange). The legacy Js.Undefined.test (removed upstream in Melange 6) is gone; testAny stays unsupported (needs runtime type tags). Melange's js_undefined_test.ml suite is ported by @davesnx

  • Align Js.Nullable with Melange 6: map/bind/iter take a labeled ~f — the previous bind had a divergent 'b t -> ('b -> 'b) -> 'b t signature vs Melange's f:('a -> 'b t) -> 'a t -> 'b t — plus isNullable/null/undefined (both represented as None natively). Melange's js_nullable_test.ml suite is ported by @davesnx

  • Implement the remaining Js.String stubs: unsafeReplaceBy0-3 (function-based regex replacement on the shared UTF-16 replace driver; non-participating capture groups are passed as "" where JS passes undefined), anchor/link (ECMA-262 CreateHTML, &quot;-escaping), localeCompare (byte-wise, no ICU collation), and toLocaleLowerCase/toLocaleUpperCase (aliased to the locale-insensitive versions). Only Js.String.make still raises (needs JS String() coercion) by @davesnx

  • Add generated per-function compatibility READMEs for Js and Belt (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_html crashing 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 in Static prerendered subtrees: the RSC HTML path now renders Writer subtrees via the regular walk (already performed for the model) and falls back to the walked HTML for Static subtrees 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 and ReactServerDOMEsbuild implements the Flight preloadModule/requireModule contract (preload starts the import and blocks the module chunk; require returns the component synchronously) by @davesnx

  • Demo: add JavaScript-identical Js.String/Js.Date...

Read more

0.4.1

Choose a tag to compare

@davesnx davesnx released this 13 Jan 20:00

CHANGES:

0.4.0

Choose a tag to compare

@davesnx davesnx released this 01 Dec 12:50
3d9f43a

CHANGES:

0.3.1

Choose a tag to compare

@davesnx davesnx released this 23 Jul 12:24
ee0f34b

CHANGES

  • Update quickjs dependency to 0.1.2 by @davesnx

0.3.0

Choose a tag to compare

@davesnx davesnx released this 22 Jul 09:39
702a5cd

CHANGES

Full Changelog: 0.2.0...0.3.0

0.2.0

Choose a tag to compare

@davesnx davesnx released this 11 Apr 15:24
84d3b3e

CHANGES

0.1.0

Choose a tag to compare

@davesnx davesnx released this 29 Feb 10:08
4ae23a9

CHANGES

Initial release of server-reason-react, includes:

  • Server-side rendering of ReasonReact components (renderToString, renderToStaticMarkup & renderToLwtStream)
  • server-reason-react.browser_ppx for skipping code from the server
  • server-reason-react.melange_ppx for enabling melange bindings and extensions which run on the server
  • server-reason-react.belt a native Belt implementation
  • server-reason-react.js a native Js implementation (unsafe and limited)
  • server-reason-react.url and server-reason-react.url-native a universal library with both implementations to work with URLs on the server and the client
  • server-reason-react.promise and server-reason-react.promise-native a universal library with both implementations to work with Promises on the server and the client. Based on https://github.com/aantron/promise
  • server-reason-react.melange-fetch a 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.webapi a 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).