Skip to content

Commit

Permalink
added experimental synchronous deep rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
abertelle committed Jun 11, 2018
1 parent 3ce00b2 commit fc53885
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 21 deletions.
80 changes: 61 additions & 19 deletions packages/melody-idom/__tests__/ComponentSpec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {
mount,
link,
getParent,
options,
} from '../src';
import { getChildren } from '../src/hierarchy';

Expand Down Expand Up @@ -80,7 +81,7 @@ describe('component', function() {
data => {
component(Component, 'test', data);
},
{ text: 'Hello' },
{ text: 'Hello' }
);
expect(el.innerHTML).toEqual('<m-placeholder></m-placeholder>');
run();
Expand All @@ -94,7 +95,7 @@ describe('component', function() {
data => {
mount(el, Component, data);
},
{ text: 'Hello' },
{ text: 'Hello' }
);
run();
expect(el.outerHTML).toEqual('<div>Hello</div>');
Expand All @@ -106,7 +107,7 @@ describe('component', function() {
data => {
component(Component, 'test', data);
},
{ text: 'Hello' },
{ text: 'Hello' }
);
run();
expect(notified).toEqual(true);
Expand All @@ -118,7 +119,7 @@ describe('component', function() {
data => {
component(Component, 'test', data);
},
{ text: 'Hello' },
{ text: 'Hello' }
);
run();
patch(
Expand All @@ -127,7 +128,7 @@ describe('component', function() {
elementOpen('div');
elementClose('div');
},
{ text: 'Hello' },
{ text: 'Hello' }
);
expect(unmounted).toEqual(true);
});
Expand All @@ -142,12 +143,12 @@ describe('component', function() {
secondChild: { text: 'World' },
});
},
{},
{}
);
expect(el.innerHTML).toEqual('<m-placeholder></m-placeholder>');
run(1);
expect(el.innerHTML).toEqual(
'<section><div>Hello</div><div>World</div></section>',
'<section><div>Hello</div><div>World</div></section>'
);

patch(
Expand All @@ -158,25 +159,66 @@ describe('component', function() {
secondChild: { text: 'universe' },
});
},
{},
{}
);
run(1);
// Updates outer element
expect(el.innerHTML).toEqual(
'<section><div>Hello</div><div>World</div></section>',
'<section><div>Hello</div><div>World</div></section>'
);
run(1);
// updates first child component
expect(el.innerHTML).toEqual(
'<section><div>hello</div><div>World</div></section>',
'<section><div>hello</div><div>World</div></section>'
);
run(1);
// updates second child component
expect(el.innerHTML).toEqual(
'<section><div>hello</div><div>universe</div></section>',
'<section><div>hello</div><div>universe</div></section>'
);
});

it('should render synchronously', function() {
// activate synchronous rendering option
options.experimentalSyncDeepRendering = true;

// initial rendering happens immediately
patch(
el,
data => {
component(ParentComponent, 'test', {
firstChild: { text: 'Hello' },
secondChild: { text: 'World' },
});
},
{}
);
expect(el.innerHTML).toEqual('<m-placeholder></m-placeholder>');
run(1);
expect(el.innerHTML).toEqual(
'<section><div>Hello</div><div>World</div></section>'
);

patch(
el,
data => {
component(ParentComponent, 'test', {
firstChild: { text: 'hello' },
secondChild: { text: 'universe' },
});
},
{}
);
run(1);
// updates outer element, first and second child component synchronously
expect(el.innerHTML).toEqual(
'<section><div>hello</div><div>universe</div></section>'
);

// deactivate synchronous rendering option
options.experimentalSyncDeepRendering = false;
});

it('should render new hierachies immediately', function() {
patch(
el,
Expand All @@ -186,11 +228,11 @@ describe('component', function() {
secondChild: { text: 'World' },
});
},
{},
{}
);
run(1);
expect(el.innerHTML).toEqual(
'<section><div>Hello</div><div>World</div></section>',
'<section><div>Hello</div><div>World</div></section>'
);
});

Expand All @@ -206,22 +248,22 @@ describe('component', function() {
secondChild: { text: 'universe' },
});
},
{},
{}
);
run(1);
// Updates outer element
expect(el.innerHTML).toEqual(
'<section><div key="child1">Hello</div><div key="child2">World</div></section>',
'<section><div key="child1">Hello</div><div key="child2">World</div></section>'
);
run(1);
// updates first child component
expect(el.innerHTML).toEqual(
'<section><div>hello</div><div key="child2">World</div></section>',
'<section><div>hello</div><div key="child2">World</div></section>'
);
run(1);
// updates second child component
expect(el.innerHTML).toEqual(
'<section><div>hello</div><div>universe</div></section>',
'<section><div>hello</div><div>universe</div></section>'
);
});

Expand All @@ -235,13 +277,13 @@ describe('component', function() {
secondChild: { text: 'World' },
});
},
{},
{}
);
expect(el.innerHTML).toEqual('<m-placeholder></m-placeholder>');
run(1);
jest.runAllTimers();
expect(el.innerHTML).toEqual(
'<section><div>Hello</div><div>World</div></section>',
'<section><div>Hello</div><div>World</div></section>'
);
});

Expand Down
2 changes: 2 additions & 0 deletions packages/melody-idom/src/options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export type Options = {
afterUpdate?: (component) => void;
/** Hook invoked immediately before a component is unmounted. */
beforeUnmount?: (component) => void;
/** Test synchronous loading of child components */
experimentalSyncDeepRendering?: boolean;
};

const options: Options = {};
Expand Down
9 changes: 7 additions & 2 deletions packages/melody-idom/src/renderQueue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import { patchOuter, updateComponent, RenderableComponent } from './core';
import { getParent } from './hierarchy';
import { debounce } from 'lodash';

import { options } from './index';
interface Node {
component: RenderableComponent;
next: Node;
Expand Down Expand Up @@ -303,7 +303,12 @@ export function flush(deadline: Deadline): void {
hasNew = true;
}
queue = concat(queue, prevQueue);
next = 0 < deadline.timeRemaining() ? pop() : null;

if (options.experimentalSyncDeepRendering) {
next = pop();
} else {
next = 0 < deadline.timeRemaining() ? pop() : null;
}
}
// notify the freshly mounted components
const notified = mounted.values();
Expand Down

0 comments on commit fc53885

Please sign in to comment.