Skip to content

Commit

Permalink
taking start and init to use
Browse files Browse the repository at this point in the history
  • Loading branch information
martypdx committed Mar 22, 2024
1 parent b79dcb2 commit 81904ee
Show file tree
Hide file tree
Showing 13 changed files with 208 additions and 259 deletions.
1 change: 1 addition & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
],
"program": "${workspaceRoot}/vite-test/node_modules/vitest/vitest.mjs",
"args": [
"--test-timeout=600000",
"-r",
"${relativeFileDirname}",
"run",
Expand Down
57 changes: 12 additions & 45 deletions packages/channels/consume.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,41 +42,8 @@ describe('promise', () => {
});


test('channel, { startWith }', async ({ fixture, find, expect }) => {
const { promise, resolve } = Promise.withResolvers();

const [LayoutChannel] = use(promise, Cat, {
startWith: <Loading />
});
fixture.append(<LayoutChannel />);

await find('loading...');
expect(fixture.innerHTML).toMatchInlineSnapshot(
`"<p>loading...</p><!--1-->"`
);

// trigger promise resolution post-loading
resolve({ name: 'felix' });
await find('felix');
expect(fixture.innerHTML).toMatchInlineSnapshot(
`"<p>felix<!--1--></p><!--1-->"`
);
});

test('fast resolve with { startWith }', async ({ fixture, find, expect }) => {
const promise = Promise.resolve({ name: 'felix' });

const [LayoutChannel] = use(promise, Cat, {
startWith: <Loading />
});
fixture.append(<>{LayoutChannel}</>);

// test that a fast resolve is the first await "find"
await find('felix');
expect(fixture.innerHTML).toMatchInlineSnapshot(`"<p>felix<!--1--></p><!--1-->"`);
});

test('branch ...channels', async ({ fixture, find, expect }) => {
test.todo('branch ...channels', async ({ fixture, find, expect }) => {
const promise = Promise.resolve(['felix', 'duchess', 'stimpy']);

const [CountChannel, ListChannel] = use(promise, CatCount, CatList);
Expand Down Expand Up @@ -111,12 +78,12 @@ describe('promise', () => {
`);
});

test('branch [channel, { startWith }], channel', async ({ fixture, find, expect }) => {
test.todo('branch [channel, { start }], channel', async ({ fixture, find, expect }) => {
const { promise, resolve } = Promise.withResolvers();

const [ListChannel, CountChannel] = use(
promise,
[CatList, { startWith: <Loading /> }],
[CatList, { start: <Loading /> }],
CatCount
);
fixture.append(<CountChannel />, <ListChannel />);
Expand Down Expand Up @@ -183,7 +150,7 @@ describe('Async Iterator', () => {
test('channel', async ({ fixture, find, expect }) => {
let cat = { name: 'felix' };
const [catChannel, dispatch] = subject(value => cat = value, {
startWith: cat
start: cat
});

const [LayoutChannel] = use(catChannel, Cat);
Expand All @@ -206,11 +173,11 @@ describe('Async Iterator', () => {
}
}

test('channel, { startWith }', async ({ fixture, find, expect }) => {
test('channel, { start }', async ({ fixture, find, expect }) => {
const [cat, dispatch] = subject();

const [LayoutChannel] = use(cat, Cat, {
startWith: <Loading />
start: <Loading />
});
fixture.append(<>{LayoutChannel}</>);

Expand All @@ -226,14 +193,14 @@ describe('Async Iterator', () => {
);
});

test('fast resolve with { startWith }', async ({ fixture, find, expect }) => {
test('fast resolve with { start }', async ({ fixture, find, expect }) => {
let cat = { name: 'felix' };
const [catChannel, dispatch] = subject(value => cat = value, {
startWith: cat
start: cat
});

const [LayoutChannel] = use(catChannel, Cat, {
startWith: <Loading />
start: <Loading />
});
fixture.append(<>{LayoutChannel}</>);

Expand All @@ -245,7 +212,7 @@ describe('Async Iterator', () => {
test('branch ...channels', async ({ fixture, find, expect }) => {
let cats = ['felix', 'duchess', 'stimpy'];
const [catsChannel, dispatch] = subject(value => cats = value, {
startWith: cats
start: cats
});

const [CountChannel, ListChannel] = use(catsChannel, CatCount, CatList);
Expand Down Expand Up @@ -301,11 +268,11 @@ describe('Async Iterator', () => {
`);
});

test('branch [channel, { startWith }], channel', async ({ fixture, find, expect }) => {
test('branch [channel, { start }], channel', async ({ fixture, find, expect }) => {
const [cats, dispatch] = subject();

const [ListChannel, CountChannel] = use(cats,
[CatList, { startWith: <Loading /> }],
[CatList, { start: <Loading /> }],
CatCount
);
fixture.append(<CountChannel />, <ListChannel />);
Expand Down
89 changes: 0 additions & 89 deletions packages/channels/gen-prime.test.poc.jsx

This file was deleted.

71 changes: 37 additions & 34 deletions packages/channels/generators.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { ConflictingOptionsError, OptionMissingFunctionArgumentError } from './throw.js';
import { Sync } from '../maya/compose/compose.js';
import { OptionMissingFunctionArgumentError } from './throw.js';

function resolveOptions(options, transform) {
let initialValue, startWith, map = false;
let start, init, map = false;
if(options) {
initialValue = options.initialValue;
startWith = options.startWith;
map = options.map ?? false;
if(initialValue !== undefined) {
if(startWith !== undefined) new ConflictingOptionsError();
if(!transform) throw new OptionMissingFunctionArgumentError('initialValue');
}
init = options.init;
start = options.start;
map = !!options.map;
if(map && !transform) {
throw new OptionMissingFunctionArgumentError();
}
}
return { initialValue, startWith, map };
return {
init, start, map,
hasStart: start !== undefined,
hasInit: init !== undefined,
};
}

export function subject(transform, options) {
Expand All @@ -23,42 +24,33 @@ export function subject(transform, options) {
transform = null;
}

const { initialValue, startWith, map } = resolveOptions(options, transform);
const { init, start, map, hasStart, hasInit } = resolveOptions(options, transform);

const relay = { resolve: null };

let unsentEarlyDispatch = null;
const maybeTransform = payload => transform ? transform(payload) : payload;

let onDeck = hasStart && hasInit ? maybeTransform(init) : null;

function dispatch(payload) {
if(transform) {
if(map) payload = payload.map(transform);
else payload = transform(payload);
}
if(map) payload = payload.map(transform);
else payload = maybeTransform(payload);

if(relay.resolve) relay.resolve(payload);
else {
// eslint-disable-next-line eqeqeq
if(payload != null) unsentEarlyDispatch = payload;
}
else onDeck = payload;
}

async function* generator() {
let promise = null;
let resolve = null;

if(initialValue !== undefined) {
yield transform(initialValue);
}
if(startWith !== undefined) {
yield startWith;
}
// this handles dispatch that happens between
// initial/start yields and main loop:
// eslint-disable-next-line eqeqeq
while(unsentEarlyDispatch != null) {
const toYield = unsentEarlyDispatch;
unsentEarlyDispatch = null;
yield toYield;
// this handles:
// 1. maybeTransformed init when init is used with start
// 2. dispatch fires via synchronous call during render
while(onDeck !== undefined) {
const received = onDeck;
onDeck = undefined;
yield received;
}

while(true) {
Expand All @@ -68,7 +60,18 @@ export function subject(transform, options) {
}
}

const asyncIterator = generator();
let asyncIterator = generator();

// eslint-disable-next-line eqeqeq
if(hasStart) {
return [Sync.wrap(start, asyncIterator), dispatch];
}
// eslint-disable-next-line eqeqeq
if(hasInit) {
const value = transform ? transform(init) : init;
return [Sync.wrap(value, asyncIterator), dispatch];
}

return [asyncIterator, dispatch];
}

Expand Down
Loading

0 comments on commit 81904ee

Please sign in to comment.