Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
- Preserve trailing comments between the type and `=` in locally abstract value constraints (`let f: type a. t /* comment */ = value`). https://github.com/rescript-lang/rescript/pull/8575
- Enforce function arity in interface/module inclusion and type coercion. Previously a curried implementation (e.g. `int => int => int`) could satisfy an uncurried interface (`(int, int) => int`) or be coerced to it, which could miscompile calls made through the interface type. Such mismatches are now compile errors with an explanatory hint. https://github.com/rescript-lang/rescript/pull/8559
- Fix termination-analysis false positives for functions whose progress flows through un-annotated helpers: collecting the callees of a function binding was accidentally disabled in 2024 (the collection guard required a node shape that uncurried code never produces), so helpers calling `@progress` functions were no longer added to the function table. https://github.com/rescript-lang/rescript/pull/8568
- Fix default values of optional parameters being computed at the wrong time for curried functions: in `(~x=default, y) => (~z=default, w) => ...`, `x`'s default was only computed when the *inner* function was applied. Each default is now computed when its own parameter group is applied. https://github.com/rescript-lang/rescript/pull/8568
- Fix default values of optional parameters being computed at the wrong time for curried functions: in `(~x=default, y) => (~z=default, w) => ...`, `x`'s default was only computed when the _inner_ function was applied. Each default is now computed when its own parameter group is applied. https://github.com/rescript-lang/rescript/pull/8568
- Fix bare labeled arrow types (`~x: int => string`) getting no arity: they printed identically to their parenthesized form (`(~x: int) => string`) but did not unify with it. https://github.com/rescript-lang/rescript/pull/8563
- Fix losses of fidelity when code passes through an external PPX: the internal `@res.async` marker no longer leaks into the program, attributes on an arrow type or on an `await` expression are no longer dropped or relocated (previously this could crash the formatter), JSX elements keep their closing tag, and PPX-emitted OCaml-style `function` is desugared instead of crashing the compiler. https://github.com/rescript-lang/rescript/pull/8561
- Preserve multibyte characters when wrapping long source lines in compiler code frames. https://github.com/rescript-lang/rescript/pull/8520
Expand All @@ -68,6 +68,7 @@

#### :house: Internal

- Developer playground: Make panes resizable with wrapping text. https://github.com/rescript-lang/rescript/pull/8628
- Merge the duplicate Lam intermediate representation into Lambda, removing the conversion layer and obsolete supporting infrastructure. Lambda is now a single private, normalized representation, with generated JavaScript remaining semantically unchanged. https://github.com/rescript-lang/rescript/pull/8608
- Add genType and source map controls and output to the developer playground. https://github.com/rescript-lang/rescript/pull/8448
- Rework the object-type representation end to end: object rows are plain field chains carrying a per-field mutability state (no phantom setter members), object literals are typed directly and property access and assignment are first-class AST and Lambda nodes shared between the Lambda and JS pipelines, and dead class-system remnants (the field-presence lattice, the class-abbreviation memo on object types, method-send typing) are removed. https://github.com/rescript-lang/rescript/pull/8597
Expand Down
2 changes: 1 addition & 1 deletion packages/dev-playground/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"prepare-pages-site": "node scripts/prepare-pages-site.mjs",
"res:build": "rescript",
"res:watch": "rescript -w",
"test": "rescript && node --test scripts/source-map-navigation.test.mjs",
"test": "rescript && node --test scripts/source-map-navigation.test.mjs scripts/pane-layout.test.mjs",
"dev": "vite --host 127.0.0.1",
"build": "rescript && vite build",
"preview": "vite preview --host 127.0.0.1"
Expand Down
64 changes: 64 additions & 0 deletions packages/dev-playground/scripts/pane-layout.test.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import assert from "node:assert/strict";
import test from "node:test";

import {
current,
finishDrag,
make,
moveDrag,
nudge,
orientationForWidth,
ratioForPosition,
setOrientation,
startDrag,
} from "../src/PaneLayout.res.mjs";

const closeTo = (actual, expected) =>
assert.ok(
Math.abs(actual - expected) < 0.000001,
`${actual} is not close to ${expected}`,
);

test("switches to stacked panes from the container width", () => {
assert.equal(orientationForWidth(901), "Columns");
assert.equal(orientationForWidth(900), "Rows");
});

test("calculates a divider ratio and respects both pane minimums", () => {
closeTo(ratioForPosition(500, 1000, 360, 420), 0.5);
closeTo(ratioForPosition(0, 1000, 360, 420), 360 / 992);
closeTo(ratioForPosition(1000, 1000, 360, 420), 1 - 420 / 992);
closeTo(ratioForPosition(100, 300, 180, 180), 0.5);
});

test("keeps drag and ratio state isolated between layout instances", () => {
const first = make();
const second = make();

assert.notEqual(first.containerId, second.containerId);
startDrag(first, 7, 600, 1000, 360, 420);

assert.equal(current(first).dragging, true);
assert.equal(current(second).dragging, false);
assert.equal(current(second).columnRatio, 0.5);

const draggedRatio = current(first).columnRatio;
moveDrag(first, 8, 450);
assert.equal(current(first).columnRatio, draggedRatio);
finishDrag(first, 8);
assert.equal(current(first).dragging, true);
finishDrag(first, 7);
assert.equal(current(first).dragging, false);
});

test("stores independent ratios for columns and stacked rows", () => {
const layout = make();

nudge(layout, 0.025, 1000, 360, 420);
closeTo(current(layout).columnRatio, 0.525);

setOrientation(layout, orientationForWidth(600));
nudge(layout, -0.025, 800, 180, 180);
closeTo(current(layout).columnRatio, 0.525);
closeTo(current(layout).rowRatio, 0.475);
});
48 changes: 43 additions & 5 deletions packages/dev-playground/src/Bindings.res
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,13 @@ module Url = {

module Event = {
@get external target: Dom.event => {..} = "target"
@get external currentTarget: Dom.event => Dom.element = "currentTarget"
@get external key: Dom.event => string = "key"
@get external button: Dom.event => int = "button"
@get external clientX: Dom.event => float = "clientX"
@get external clientY: Dom.event => float = "clientY"
@get external pointerId: Dom.event => int = "pointerId"
@get external detail: Dom.event => int = "detail"
@send external preventDefault: Dom.event => unit = "preventDefault"

let value = (event: Dom.event): string => (event->target)["value"]
Expand All @@ -129,11 +135,6 @@ module Event = {
let scrollTop: float = (event->target)["scrollTop"]
scrollTop->Math.round->Float.toInt
}

let scrollLeft = (event: Dom.event): int => {
let scrollLeft: float = (event->target)["scrollLeft"]
scrollLeft->Math.round->Float.toInt
}
}

module EventTarget = {
Expand All @@ -160,6 +161,20 @@ type scrollIntoViewOptions = {
inline: string,
}

type boundingRect = {
left: float,
top: float,
width: float,
height: float,
}

type classList

module ClassList = {
@send external add: (classList, string) => unit = "add"
@send external remove: (classList, string) => unit = "remove"
}

module Element = {
@send external setAttribute: (Dom.element, string, string) => unit = "setAttribute"
@send
Expand All @@ -170,6 +185,15 @@ module Element = {
@send external appendChild: (Dom.element, Dom.element) => unit = "appendChild"
@send external removeChild: (Dom.element, Dom.element) => unit = "removeChild"
@send external focus: Dom.element => unit = "focus"
@send external setPointerCapture: (Dom.element, int) => unit = "setPointerCapture"
@send external releasePointerCapture: (Dom.element, int) => unit = "releasePointerCapture"
@send external hasPointerCapture: (Dom.element, int) => bool = "hasPointerCapture"
@send external getBoundingClientRect: Dom.element => boundingRect = "getBoundingClientRect"
@get external classList: Dom.element => classList = "classList"
@send @return(nullable)
external querySelector: (Dom.element, string) => option<Dom.element> = "querySelector"
@get @return(nullable)
external parentElement: Dom.element => option<Dom.element> = "parentElement"
@send
external scrollIntoView: (Dom.element, scrollIntoViewOptions) => unit = "scrollIntoView"
@get external style: Dom.element => CssStyle.t = "style"
Expand All @@ -181,6 +205,20 @@ module Element = {
"__devPlaygroundScrollHandler"
}

type resizeObserver
type resizeObserverEntry

module ResizeObserverEntry = {
@get external contentRect: resizeObserverEntry => boundingRect = "contentRect"
}

module ResizeObserver = {
@val external supported: option<unknown> = "globalThis.ResizeObserver"
@new external make: (array<resizeObserverEntry> => unit) => resizeObserver = "ResizeObserver"
@send external observe: (resizeObserver, Dom.element) => unit = "observe"
@send external disconnect: resizeObserver => unit = "disconnect"
}

module ScriptElement = {
@set external setSrc: (Dom.element, string) => unit = "src"
@set external setAsync: (Dom.element, bool) => unit = "async"
Expand Down
Loading
Loading