Skip to content

Commit

Permalink
fix(runtime): dispatch queue events before willLoad
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Jul 3, 2019
1 parent b05ae9c commit 2d1a0aa
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/declarations/runtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ export interface HostRef {
$onReadyPromise$?: Promise<any>;
$onReadyResolve$?: (elm: any) => void;
$vnode$?: d.VNode;
$queuedListeners$?: [string, any][];
$rmListeners$?: () => void;
$modeName$?: string;
}
Expand Down
13 changes: 7 additions & 6 deletions src/runtime/host-listener.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import * as d from '../declarations';
import { BUILD } from '@build-conditionals';
import { consoleError, doc, plt, supportsListenerOptions, win } from '@platform';
import { LISTENER_FLAGS } from '@utils';
import { doc, plt, supportsListenerOptions, win } from '@platform';
import { HOST_FLAGS, LISTENER_FLAGS } from '@utils';


export const addEventListeners = (elm: d.HostElement, hostRef: d.HostRef, listeners: d.ComponentRuntimeHostListener[]) => {
hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || [];
const removeFns = listeners.map(([flags, name, method]) => {
const target = (BUILD.hostListenerTarget ? getHostListenerTarget(elm, flags) : elm);
const handler = hostListenerProxy(hostRef, method);
Expand All @@ -18,15 +19,15 @@ export const addEventListeners = (elm: d.HostElement, hostRef: d.HostRef, listen
const hostListenerProxy = (hostRef: d.HostRef, methodName: string) => {
return (ev: Event) => {
if (BUILD.lazyLoad) {
if (hostRef.$lazyInstance$) {
if (hostRef.$flags$ & HOST_FLAGS.isMethodsCallable) {
// instance is ready, let's call it's member method for this event
return hostRef.$lazyInstance$[methodName](ev);
hostRef.$lazyInstance$[methodName](ev);

} else {
return hostRef.$onReadyPromise$.then(() => hostRef.$lazyInstance$[methodName](ev)).catch(consoleError);
hostRef.$queuedListeners$.push([methodName, ev]);
}
} else {
return (hostRef.$hostElement$ as any)[methodName](ev);
(hostRef.$hostElement$ as any)[methodName](ev);
}
};
};
Expand Down
2 changes: 1 addition & 1 deletion src/runtime/set-value.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export const setValue = (ref: d.RuntimeRef, propName: string, newVal: any, cmpMe

if (!BUILD.lazyLoad || hostRef.$lazyInstance$) {
// get an array of method names of watch functions to call
if (BUILD.watchCallback && cmpMeta.$watchers$ && flags & HOST_FLAGS.isWatchReady) {
if (BUILD.watchCallback && cmpMeta.$watchers$ && flags & HOST_FLAGS.isMethodsCallable) {
const watchMethods = cmpMeta.$watchers$[propName];

if (watchMethods) {
Expand Down
51 changes: 51 additions & 0 deletions src/runtime/test/listen.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,57 @@ describe('listen', () => {
expect(root).toEqualHtml(`
<cmp-a>1,2,4,5,6</cmp-a>
`);
});

it('listen before load', async () => {
let log = '';
@Component({ tag: 'cmp-a'})
class CmpA {
@Listen('event')
onEvent(ev: CustomEvent<string>) {
log += ev.detail;
}

connectedCallback() {
log += 'connectedCallback ';
}

componentWillLoad() {
log += 'componentWillLoad ';
}

componentDidLoad() {
log += 'componentDidLoad ';
}

render() {
return `${log}`;
}
}

const { doc, waitForChanges } = await newSpecPage({
components: [CmpA],
html: '',
});

const a = doc.createElement('cmp-a');
doc.body.appendChild(a);

a.dispatchEvent(new CustomEvent('event', {
detail: 'event1 '
}));
a.dispatchEvent(new CustomEvent('event', {
detail: 'event2 '
}));
a.dispatchEvent(new CustomEvent('event', {
detail: 'event3 '
}));

await Promise.resolve();
expect(log).toEqualHtml('');

await waitForChanges();
expect(log).toEqualHtml(`connectedCallback event1 event2 event3 componentWillLoad componentDidLoad`);
});

});
12 changes: 8 additions & 4 deletions src/runtime/update-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { HYDRATED_CLASS, PLATFORM_FLAGS } from './runtime-constants';
import { renderVdom } from './vdom/vdom-render';


export const safeCall = async (instance: any, method: string) => {
export const safeCall = async (instance: any, method: string, arg?: any) => {
if (instance && instance[method]) {
try {
await instance[method]();
await instance[method](arg);
} catch (e) {
consoleError(e);
}
Expand All @@ -23,8 +23,12 @@ export const scheduleUpdate = async (elm: d.HostElement, hostRef: d.HostRef, cmp
}
const instance = BUILD.lazyLoad ? hostRef.$lazyInstance$ : elm as any;
if (isInitialLoad) {
if (BUILD.watchCallback) {
hostRef.$flags$ |= HOST_FLAGS.isWatchReady;
if (BUILD.watchCallback || BUILD.hostListener) {
hostRef.$flags$ |= HOST_FLAGS.isMethodsCallable;
}
if (BUILD.hostListener && hostRef.$queuedListeners$) {
hostRef.$queuedListeners$.forEach(([methodName, event]) => safeCall(instance, methodName, event));
hostRef.$queuedListeners$ = null;
}
emitLifecycleEvent(elm, 'componentWillLoad');
if (BUILD.cmpWillLoad) {
Expand Down
2 changes: 1 addition & 1 deletion src/utils/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export const enum HOST_FLAGS {
isQueuedForUpdate = 1 << 4,
hasInitializedComponent = 1 << 5,
hasLoadedComponent = 1 << 6,
isWatchReady = 1 << 7,
isMethodsCallable = 1 << 7,
}

export const enum CMP_FLAGS {
Expand Down

0 comments on commit 2d1a0aa

Please sign in to comment.