Skip to content

Commit

Permalink
feat(): add setErrorHandler() (#2704)
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Oct 15, 2020
1 parent 99ef518 commit 5d2780a
Show file tree
Hide file tree
Showing 9 changed files with 33 additions and 14 deletions.
5 changes: 4 additions & 1 deletion src/client/client-log.ts
@@ -1,5 +1,8 @@
import type * as d from '../declarations';
import { BUILD } from '@app-data';

export let consoleError: d.ErrorHandler = (e: any, _?: any) => console.error(e);

export const STENCIL_DEV_MODE = BUILD.isTesting
? ['STENCIL:'] // E2E testing
: ['%cstencil', 'color: white;background:#4c47ff;font-weight: bold; font-size:10px; padding:2px 6px; border-radius: 5px'];
Expand All @@ -10,4 +13,4 @@ export const consoleDevWarn = (...m: any[]) => console.warn(...STENCIL_DEV_MODE,

export const consoleDevInfo = (...m: any[]) => console.info(...STENCIL_DEV_MODE, ...m);

export const consoleError = (e: any) => console.error(e);
export const setErrorHandler = (handler: d.ErrorHandler) => consoleError = handler;
1 change: 1 addition & 0 deletions src/compiler/transformers/update-stencil-core-import.ts
Expand Up @@ -70,4 +70,5 @@ const KEEP_IMPORTS = new Set([
'forceUpdate',
'getRenderingRef',
'forceModeUpdate',
'setErrorHandler'
]);
9 changes: 9 additions & 0 deletions src/declarations/stencil-public-runtime.ts
Expand Up @@ -245,6 +245,8 @@ export declare const Watch: WatchDecorator;

export type ResolutionHandler = (elm: HTMLElement) => string | undefined | null;

export type ErrorHandler = (err: any, element?: HTMLElement) => void;

/**
* `setMode()` is used for libraries which provide multiple "modes" for styles.
*/
Expand Down Expand Up @@ -312,6 +314,13 @@ export declare function writeTask(task: RafCallback): void;
* For further information: https://developers.google.com/web/fundamentals/performance/rendering/avoid-large-complex-layouts-and-layout-thrashing
*/
export declare function readTask(task: RafCallback): void;

/**
* `setErrorHandler()` can be used to inject a custom global error handler.
* Unhandled exception raised while rendering, during event handling, or lifecycles will trigger the custom event handler.
*/
export declare const setErrorHandler: (handler: ErrorHandler) => void;

/**
* This file gets copied to all distributions of stencil component collections.
* - no imports
Expand Down
1 change: 1 addition & 0 deletions src/internal/stencil-core/index.d.ts
Expand Up @@ -44,6 +44,7 @@ export {
State,
Watch,
writeTask,
setErrorHandler,
} from '../stencil-public-runtime';

export type { StencilConfig as Config, PrerenderConfig } from '../stencil-public-compiler';
1 change: 1 addition & 0 deletions src/internal/stencil-core/index.js
Expand Up @@ -11,4 +11,5 @@ export {
setMode,
setAssetPath,
writeTask,
setErrorHandler,
} from '../client/index.js';
20 changes: 12 additions & 8 deletions src/runtime/host-listener.ts
@@ -1,6 +1,6 @@
import type * as d from '../declarations';
import { BUILD } from '@app-data';
import { doc, plt, supportsListenerOptions, win } from '@platform';
import { doc, plt, consoleError, supportsListenerOptions, win } from '@platform';
import { HOST_FLAGS, LISTENER_FLAGS } from '@utils';

export const addHostEventListeners = (elm: d.HostElement, hostRef: d.HostRef, listeners: d.ComponentRuntimeHostListener[], attachParentListeners: boolean) => {
Expand Down Expand Up @@ -36,15 +36,19 @@ export const addHostEventListeners = (elm: d.HostElement, hostRef: d.HostRef, li
};

const hostListenerProxy = (hostRef: d.HostRef, methodName: string) => (ev: Event) => {
if (BUILD.lazyLoad) {
if (hostRef.$flags$ & HOST_FLAGS.isListenReady) {
// instance is ready, let's call it's member method for this event
hostRef.$lazyInstance$[methodName](ev);
try {
if (BUILD.lazyLoad) {
if (hostRef.$flags$ & HOST_FLAGS.isListenReady) {
// instance is ready, let's call it's member method for this event
hostRef.$lazyInstance$[methodName](ev);
} else {
(hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]);
}
} else {
(hostRef.$queuedListeners$ = hostRef.$queuedListeners$ || []).push([methodName, ev]);
(hostRef.$hostElement$ as any)[methodName](ev);
}
} else {
(hostRef.$hostElement$ as any)[methodName](ev);
} catch (e) {
consoleError(e);
}
};

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/set-value.ts
Expand Up @@ -57,7 +57,7 @@ export const setValue = (ref: d.RuntimeRef, propName: string, newVal: any, cmpMe
// fire off each of the watch methods that are watching this property
instance[watchMethodName](newVal, oldVal, propName);
} catch (e) {
consoleError(e);
consoleError(e, elm);
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/update-component.ts
Expand Up @@ -117,7 +117,7 @@ const updateComponent = async (hostRef: d.HostRef, instance: any, isInitialLoad:
}
}
} catch (e) {
consoleError(e);
consoleError(e, elm);
}
}

Expand Down Expand Up @@ -170,7 +170,7 @@ const callRender = (hostRef: d.HostRef, instance: any) => {
hostRef.$flags$ |= HOST_FLAGS.hasRendered;
}
} catch (e) {
consoleError(e);
consoleError(e, hostRef.$hostElement$);
}
renderingRef = null;
return instance;
Expand Down
4 changes: 2 additions & 2 deletions src/runtime/vdom/vdom-render.ts
Expand Up @@ -9,7 +9,7 @@
import type * as d from '../../declarations';
import { BUILD } from '@app-data';
import { CMP_FLAGS, HTML_NS, SVG_NS, isDef } from '@utils';
import { consoleError, doc, plt, supportsShadow } from '@platform';
import { consoleDevError, doc, plt, supportsShadow } from '@platform';
import { h, isHost, newVNode } from './h';
import { NODE_TYPE, PLATFORM_FLAGS, VNODE_FLAGS } from '../runtime-constants';
import { updateElement } from './update-element';
Expand Down Expand Up @@ -52,7 +52,7 @@ const createElm = (oldParentVNode: d.VNode, newParentVNode: d.VNode, childIndex:
}

if (BUILD.isDev && newVNode.$elm$) {
consoleError(
consoleDevError(
`The JSX ${
newVNode.$text$ !== null ? `"${newVNode.$text$}" text` : `"${newVNode.$tag$}" element`
} node should not be shared within the same renderer. The renderer caches element lookups in order to improve performance. However, a side effect from this is that the exact same JSX node should not be reused. For more information please see https://stenciljs.com/docs/templating-jsx#avoid-shared-jsx-nodes`,
Expand Down

0 comments on commit 5d2780a

Please sign in to comment.