Skip to content

Commit

Permalink
Bugfix: 'ref' not available reliably (#200)
Browse files Browse the repository at this point in the history
* Start reconciler tests

* Add test for ref'ing

* Get tests green w/ delayed callback fix

* Convert component

* Remove 'flushEvents' becasue it is no longer needed

* Clean up comments

* Formatting
  • Loading branch information
bryphe authored Jan 18, 2019
1 parent eea924d commit bfaac51
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/UI/Node.re
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ open Revery_Math;
module UniqueId =
Revery_Core.UniqueId.Make({});

type callback = unit => unit;

class node ('a) (()) = {
as _this;
val _children: ref(list(node('a))) = ref([]);
Expand Down Expand Up @@ -110,6 +112,7 @@ class node ('a) (()) = {
List.filter(c => c#getInternalId() != n#getInternalId(), _children^);
n#_setParent(None);
};
pub firstChild = () => List.hd(_children^);
pub getParent = () => _parent^;
pub getChildren = () => _children^;
pub getMeasureFunction = (_pixelRatio: float) => None;
Expand Down
2 changes: 1 addition & 1 deletion src/UI/Revery_UI.re
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ let start =

let rootNode = (new viewNode)();
let mouseCursor: Mouse.Cursor.t = Mouse.Cursor.make();
let container = React.Container.createContainer(rootNode);
let container = React.Container.create(rootNode);
let ui =
UiContainer.create(
window,
Expand Down
5 changes: 2 additions & 3 deletions src/UI/UiReact.re
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ module Container = {
state: option(state),
};

let createContainer: UiReconciler.reveryNode => t =
n => {node: n, state: None};
let create: UiReconciler.reveryNode => t = n => {node: n, state: None};

let updateContainer: (t, React.syntheticElement) => t =
let update: (t, React.syntheticElement) => t =
({node, state}, element) => {
let newRendered =
switch (state) {
Expand Down
2 changes: 1 addition & 1 deletion src/UI/UiRender.re
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ let render = (container: UiContainer.t, component: UiReact.syntheticElement) =>
AnimationTicker.tick();

/* Perform reconciliation */
container := UiReact.Container.updateContainer(container^, component);
container := UiReact.Container.update(container^, component);

/* Layout */
let size = Window.getSize(window);
Expand Down
2 changes: 1 addition & 1 deletion src/UI/ViewNode.re
Original file line number Diff line number Diff line change
Expand Up @@ -277,11 +277,11 @@ let renderShadow = (~boxShadow, ~width, ~height, ~world, ~m) => {

class viewNode (()) = {
as _this;
val solidShader = Assets.solidShader();
inherit (class node(renderPass))() as _super;
pub! draw = (pass: renderPass, parentContext: NodeDrawContext.t) => {
switch (pass) {
| AlphaPass(m) =>
let solidShader = Assets.solidShader();
let dimensions = _this#measurements();
let width = float_of_int(dimensions.width);
let height = float_of_int(dimensions.height);
Expand Down
4 changes: 3 additions & 1 deletion test/UI/MouseTest.re
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,9 @@ test("Mouse", () => {

expect(count^).toBe(1);
});
test("does trigger onBlur for node after cursor is pressed outside the node", () => {
test(
"does trigger onBlur for node after cursor is pressed outside the node",
() => {
let cursor = Mouse.Cursor.make();
Mouse.Cursor.set(cursor, Revery_Math.Vec2.create(50.0, 50.0));

Expand Down
89 changes: 89 additions & 0 deletions test/UI/ReconcilerTests.re
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
open Rejest;

open Revery_UI;

/*
* This module tests the integration of the Brisk reconciler - `React` -
* with our Node tree.
*/

module TestRefComponent = {
let component = React.component("TestRefComponent");

let make = (~latestRef, ()) =>
component(slots => {
let (refFromState, setRef, _slots: React.Hooks.empty) =
React.Hooks.state(None, slots);

latestRef := refFromState;

let setRefInState = r => {
prerr_endline("SET REF IN STATE");
setRef(Some(r));
};

<View ref=setRefInState />;
});

let createElement = (~children as _, ~latestRef, ()) =>
React.element(make(~latestRef, ()));
};

test("Reconciler", () => {
test("reconcile adds a child", () => {
let rootNode = (new viewNode)();

let container = React.Container.create(rootNode);
React.Container.update(container, <View />) |> ignore;

expect(List.length(rootNode#getChildren())).toBe(1);
});

test("ref: returns value of node", () => {
let rootNode = (new viewNode)();

let container = React.Container.create(rootNode);

/* Use a ref to track the latest value of the `ref={..}` callback */
let referenceNode = ref(None);

let refCallback = r => {
referenceNode := Some(r);
};

React.Container.update(container, <View ref=refCallback />) |> ignore;

/* And validate that we actually got the right one, based on the node ID! */
switch (referenceNode^) {
| Some(r) =>
let actualChild = rootNode#firstChild();
expect(actualChild#getInternalId()).toBe(r#getInternalId());
| None => expect(0).toBe(1)
};
});

test("ref: validate ref gets passed back to component", () => {
let rootNode = (new viewNode)();

let container = React.Container.create(rootNode);

/*
* Hold a `ref` that tracks the last refNode that comes from RENDER -
* this also exercises the interplay between the `ref` callback and `useState`
*/
let latestRef: ref(option(viewNode)) = ref(None);

/* First update - this will end up 'mounting' the node and dispatching the 'ref' callback */
/* However - the state won't be updated - it will just be queued up */
let update1 =
React.Container.update(container, <TestRefComponent latestRef />);

/* We need to update again to pick up the state update */
React.Container.update(update1, <TestRefComponent latestRef />) |> ignore;

switch (latestRef^) {
| Some(_) => expect(1).toBe(1)
| None => expect(0).toBe(1)
};
});
});

0 comments on commit bfaac51

Please sign in to comment.