Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refacto(*): the signal is not part of the core anymore
Browse files Browse the repository at this point in the history
lorenzofox3 committed Mar 11, 2024
1 parent 941a3a8 commit 4b0bbbf
Showing 20 changed files with 110 additions and 130 deletions.
21 changes: 13 additions & 8 deletions apps/restaurant-cashier/cart/cart.controller.js
Original file line number Diff line number Diff line change
@@ -3,24 +3,29 @@ import { cartEvents, cartService } from './cart.service.js';
export const createCartController =
({ cartService }) =>
(comp) =>
function* ({ $signal, $host, ...rest }) {
function* ({ $host, ...rest }) {
const { render } = $host;
const abortController = new AbortController();
const { signal } = abortController;
$host.render = (args = {}) =>
render({
...args,
...cartService.getState(),
});

cartService.on(cartEvents.CART_CHANGED, () => $host.render(), {
signal: $signal,
signal,
});

yield* comp({
$host,
$signal,
cartService,
...rest,
});
try {
yield* comp({
$host,
cartService,
...rest,
});
} finally {
abortController.abort();
}
};

export const withCartController = createCartController({ cartService });
22 changes: 14 additions & 8 deletions apps/restaurant-cashier/components/ui-alert.component.js
Original file line number Diff line number Diff line change
@@ -25,27 +25,33 @@ p {
`;

const connectToNotifications = (comp) =>
function* ({ notificationsService, $signal, $host, ...rest }) {
function* ({ notificationsService, $host, ...rest }) {
const controller = new AbortController();
const { signal } = controller;
notificationsService.on(
notificationsEvents.messagePublished,
({ detail }) => {
if (detail.level === 'error') {
$host.render({ notification: detail.payload });
}
},
{ signal: $signal },
{ signal: controller.signal },
);

yield* comp({
$host,
$signal,
...rest,
});
try {
yield* comp({
$host,
signal,
...rest,
});
} finally {
controller.abort();
}
};
export const UIAlert = connectToNotifications(function* ({
$host,
$root,
$signal: signal,
signal,
}) {
const duration = $host.hasAttribute('duration')
? Number($host.getAttribute('duration'))
6 changes: 3 additions & 3 deletions apps/restaurant-cashier/dashboard/dashboard.controller.js
Original file line number Diff line number Diff line change
@@ -2,8 +2,8 @@ import { http } from '../utils/http.js';
import { compose } from '../utils/functions.js';

export const withChartData = (comp) => {
return function* ({ $host, $signal, ...rest }) {
http($host.dataset.url, { signal: $signal }).then($host.render);
yield* comp({ $host, $signal, ...rest });
return function* ({ $host, ...rest }) {
http($host.dataset.url).then($host.render);
yield* comp({ $host, ...rest });
};
};
Original file line number Diff line number Diff line change
@@ -70,7 +70,9 @@ img[src=''] {
<img aria-hidden="true" alt="" />
`;

export const ImageUploader = function* ({ $host, $root, $signal: signal }) {
export const ImageUploader = function* ({ $host, $root }) {
const abortController = new AbortController();
const { signal } = abortController;
$root.append(template.content.cloneNode(true));
const img = $root.querySelector('img');
const input = $root.querySelector('input');
@@ -87,13 +89,17 @@ export const ImageUploader = function* ({ $host, $root, $signal: signal }) {
handleFileChange(file);
});

while (true) {
const { attributes } = yield;
const { url = '', status = 'idle' } = attributes;
const label = getLabel({ url, status });
input.disabled = button.disabled = status === 'loading';
button.textContent = label;
img.setAttribute('src', url);
try {
while (true) {
const { attributes } = yield;
const { url = '', status = 'idle' } = attributes;
const label = getLabel({ url, status });
input.disabled = button.disabled = status === 'loading';
button.textContent = label;
img.setAttribute('src', url);
}
} finally {
abortController.abort();
}

async function handleFileChange(file) {
12 changes: 9 additions & 3 deletions apps/restaurant-cashier/products/product-list.controller.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
export const createProductListController =
({ productListService }) =>
(comp) =>
function* ({ $signal, $host, ...rest }) {
function* ({ $host, ...rest }) {
const { render } = $host;
const abortController = new AbortController();
const { signal } = abortController;
$host.render = (args = {}) => {
render({
...args,
@@ -16,9 +18,13 @@ export const createProductListController =
$host.render();
},
{
signal: $signal,
signal,
},
);

yield* comp({ $signal, $host, productListService, ...rest });
try {
yield* comp({ $host, productListService, ...rest });
} finally {
abortController.abort();
}
};
12 changes: 9 additions & 3 deletions apps/restaurant-cashier/router/page-link.component.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { navigationEvents } from './router.js';

export const connectToRouter = (component) =>
function* ({ router, $host, $signal, ...rest }) {
function* ({ router, $host, ...rest }) {
const abortController = new AbortController();
const { signal } = abortController;
const linkHref = $host.getAttribute('href');
router.on(
navigationEvents.ROUTE_CHANGE_SUCCEEDED,
@@ -10,15 +12,19 @@ export const connectToRouter = (component) =>
const isCurrent = requestedPathname.includes(linkHref);
$host.render({ isCurrent });
},
{ signal: $signal },
{ signal },
);

$host.addEventListener('click', (ev) => {
ev.preventDefault();
router.goTo(linkHref);
});

yield* component({ router, $host, $signal, ...rest });
try {
yield* component({ router, $host, ...rest });
} finally {
abortController.abort();
}
};

export const PageLink = connectToRouter(function* ({ $host }) {
22 changes: 14 additions & 8 deletions apps/restaurant-cashier/router/page-outlet.component.js
Original file line number Diff line number Diff line change
@@ -2,20 +2,26 @@ import { navigationEvents } from './router.js';
import { motionSettings } from '../users/preferences.service.js';

const pageOutlet = (component) =>
function* ({ router, $host, $signal, ...rest }) {
function* ({ router, $host, ...rest }) {
const abortController = new AbortController();
const { signal } = abortController;
const render = $host.render.bind($host);
router.on(
navigationEvents.PAGE_LOADED,
({ detail }) => render({ ...detail }),
{ signal: $signal },
{ signal },
);

yield* component({
$host,
$signal,
router,
...rest,
});
try {
yield* component({
$host,
signal,
router,
...rest,
});
} finally {
abortController.abort();
}
};

export const PageOutlet = pageOutlet(function* ({ $host, preferencesService }) {
7 changes: 4 additions & 3 deletions apps/restaurant-cashier/users/preferences.controller.js
Original file line number Diff line number Diff line change
@@ -3,7 +3,9 @@ import { preferencesEvents } from './preferences.service.js';
export const createPreferencesController =
({ preferencesService }) =>
(comp) =>
function* ({ $signal, $host, ...rest }) {
function* ({ $host, ...rest }) {
const abortController = new AbortController();
const { signal } = abortController;
const { render } = $host;
$host.render = (args = {}) => {
render({
@@ -18,12 +20,11 @@ export const createPreferencesController =
$host.render();
},
{
signal: $signal,
signal,
},
);

yield* comp({
$signal,
$host,
preferencesService,
...rest,
11 changes: 7 additions & 4 deletions apps/todomvc/todo-list.controller.ts
Original file line number Diff line number Diff line change
@@ -12,11 +12,11 @@ export const connectTodoService = (
) => {
return injectTodoService(connector);
function* connector({
$signal,
todoService,
$host,
...deps
}: ComponentDependencies<{ todoService: TodoService }>) {
const abortController = new AbortController();
const { render: _render } = $host;

$host.render = (args?) =>
@@ -26,9 +26,12 @@ export const connectTodoService = (
});

todoService.addEventListener('state-changed', $host.render, {
signal: $signal,
signal: abortController.signal,
});

yield* comp({ $signal, $host, todoService, ...deps });
try {
yield* comp({ $host, todoService, ...deps });
} finally {
abortController.abort();
}
}
};
10 changes: 4 additions & 6 deletions apps/todomvc/views/todo-list.view.ts
Original file line number Diff line number Diff line change
@@ -4,15 +4,15 @@ import { ViewFactory } from '@cofn/view';
export const TodoListView: ViewFactory<
{ todoService: TodoService },
{ state: TodoServiceState }
> = ({ html, todoService, $host, $signal }) => {
> = ({ html, todoService, $host }) => {
bind('todo-toggled', todoService.toggleTodo);
bind('todo-removed', (detail) => {
todoService.removeTodo(detail);
$host.focus();
});
const treeWalker = document.createTreeWalker($host, NodeFilter.SHOW_ELEMENT);
$host.addEventListener('keydown', handleKeydown, { signal: $signal });
$host.addEventListener('focus', handleFocus, { signal: $signal });
$host.addEventListener('keydown', handleKeydown);
$host.addEventListener('focus', handleFocus);

return ({ state }) => {
const { displayedItems = [] } = getModelFromState(state);
@@ -29,9 +29,7 @@ export const TodoListView: ViewFactory<
};

function bind(eventName, listener) {
$host.addEventListener(eventName, ({ detail }) => listener(detail), {
signal: $signal,
});
$host.addEventListener(eventName, ({ detail }) => listener(detail));
}

function handleKeydown({ key }) {
1 change: 0 additions & 1 deletion packages/controllers/test/index.js
Original file line number Diff line number Diff line change
@@ -44,7 +44,6 @@ test('controller function get passed the routine dependencies along with the sta
}) => {
let hasBeenChecked = false;
const withSimpleController = withController((deps) => {
ok(deps.$signal);
ok(deps.$host);
ok(deps.$root);
ok(deps.state);
4 changes: 0 additions & 4 deletions packages/core/src/component.js
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@ export const component = (renderLoop, opts = defaultOptions) => {
const { observedAttributes = [], Klass = HTMLElement, shadow } = opts;
return class extends Klass {
#loop;
#abortController;
#updateStack = [];

static get observedAttributes() {
@@ -15,13 +14,11 @@ export const component = (renderLoop, opts = defaultOptions) => {

constructor() {
super();
this.#abortController = new AbortController();
const $host = this;
const $root = shadow !== undefined ? $host.attachShadow(shadow) : $host;
this.#loop = renderLoop.bind(this)({
$host,
$root,
$signal: this.#abortController.signal,
});
this.render = this.render.bind(this);
this.#loop.next();
@@ -35,7 +32,6 @@ export const component = (renderLoop, opts = defaultOptions) => {
// we end the rendering loop only if the component is removed from de DOM. Sometimes it is just moved from one place to another one
window.queueMicrotask(() => {
if (this.isConnected === false) {
this.#abortController.abort();
this.#loop.return();
}
});
1 change: 0 additions & 1 deletion packages/core/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
type ComponentTag = `${string}-${string}`;

export type ComponentDependencies<T = unknown> = T & {
$signal: AbortSignal;
$host: HTMLElement & {
render: <Update extends Record<unknown, unknown>>(input?: Update) => void;
};
53 changes: 0 additions & 53 deletions packages/core/test/abort-signal.test.js

This file was deleted.

1 change: 0 additions & 1 deletion packages/core/test/test-suite.html
Original file line number Diff line number Diff line change
@@ -18,7 +18,6 @@ <h1>Test reporting</h1>
import { report, createHTMLReporter, createSocketSink } from '@cofn/test-lib/client';
import './simple-component.test.js';
import './reactive-attributes.test.js';
import './abort-signal.test.js';
import './shadow-dom.test.js';

const [st1, st2] = report().tee();
Empty file.
18 changes: 9 additions & 9 deletions packages/view/src/active-site.js
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ export const findOrCreateTemplateRecord = ({
templateParts,
interpolatedValues,
templateCache,
$signal,
signal,
}) => {
const { template, ...blueprint } = buildBlueprint({
templateParts,
@@ -30,7 +30,7 @@ export const findOrCreateTemplateRecord = ({
interpolatedValues: blueprint.isKeyed
? interpolatedValues.slice(1)
: interpolatedValues,
$signal,
signal,
}),
});
}
@@ -63,14 +63,14 @@ const createUpdateFns = ({
content,
interpolatedValues,
templateCache,
$signal,
signal,
}) =>
traverseTree(content).map((node, index) =>
createUpdateFn({
node,
initialValue: interpolatedValues[index],
templateCache,
$signal,
signal,
}),
);

@@ -104,7 +104,7 @@ const createUpdateDOMNode = ({ node, templateCache }) => {

const createUpdateListener = ({
node: { ownerElement, name: attributeName },
$signal: signal,
signal: signal,
}) => {
ownerElement.removeAttribute(attributeName);
const update = (value) => {
@@ -141,11 +141,11 @@ const createUpdateAttribute =
return value;
};

const createAttributeNodeUpdateFn = ({ node, $signal }) => {
const createAttributeNodeUpdateFn = ({ node, signal }) => {
const { name: attributeName } = node;

if (attributeName.startsWith('@')) {
return createUpdateListener({ node, $signal });
return createUpdateListener({ node, signal });
}

if (attributeName.startsWith('.')) {
@@ -162,10 +162,10 @@ const updateFunctionMap = {
3: createTextOrElementNodeUpdateFn,
};

const createUpdateFn = ({ node, initialValue, templateCache, $signal }) =>
const createUpdateFn = ({ node, initialValue, templateCache, signal }) =>
updateFunctionMap[node.nodeType]({
node,
initialValue,
templateCache,
$signal,
signal,
});
4 changes: 2 additions & 2 deletions packages/view/src/index.d.ts
Original file line number Diff line number Diff line change
@@ -19,9 +19,9 @@ export type ComponentDependencies<T = unknown> = _ComponentDependencies<
>;

export declare function createHTML({
$signal,
signal,
}: {
$signal: AbortSignal;
signal: AbortSignal;
}): TemplateTagFunction;

type ViewFunction<State = unknown> = (
11 changes: 7 additions & 4 deletions packages/view/src/index.js
Original file line number Diff line number Diff line change
@@ -8,11 +8,13 @@ const zip = (array1, array2) =>

export const withView = (viewFactory) =>
function* (deps) {
const { $root, $signal } = deps;
const abortController = new AbortController();
const signal = abortController.signal;
const { $root } = deps;
const templateCache = new Map();
const view = viewFactory({
...deps,
html: createHTML({ $signal, templateCache }),
html: createHTML({ signal, templateCache }),
});

const viewFn = typeof view === 'function' ? view : () => view;
@@ -27,17 +29,18 @@ export const withView = (viewFactory) =>
}
} finally {
templateCache.clear();
abortController.abort();
}
};

export const createHTML =
({ $signal, templateCache }) =>
({ signal, templateCache }) =>
(templateParts, ...interpolatedValues) => {
const templateRecord = findOrCreateTemplateRecord({
templateParts,
interpolatedValues,
templateCache,
$signal,
signal,
});

const actualValues = templateRecord.isKeyed
2 changes: 1 addition & 1 deletion packages/view/test/event-listeners.test.js
Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@ test('when element is removed all listeners are removed', async ({ eq }) => {
count += 1;
};

const el = fromView(({ html, $signal }) => {
const el = fromView(({ html }) => {
return () => html`<button @click="${listener}">click</button>`;
});

0 comments on commit 4b0bbbf

Please sign in to comment.