diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 3e4801054757..63e35125091b 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -22,6 +22,7 @@ export interface Fragment { /* outro */ o: (local: any) => void; /* destroy */ d: (detaching: 0 | 1) => void; } + interface T$$ { dirty: number[]; ctx: null | any; @@ -41,6 +42,20 @@ interface T$$ { root:Element | ShadowRoot } +/** + * bind_events + * Binds the events provided in options.props, to named callbacks event:bindings + * @param props + */ +function bind_events(props) { + const events = props && props['event:bindings'] ? props['event:bindings'] : {}; + + if (Object.keys(events).length) { + delete props['event:bindings']; + } + return events; +} + export function bind(component, name, callback) { const index = component.$$.props[name]; if (index !== undefined) { @@ -127,7 +142,7 @@ export function init(component, options, instance, create_fragment, not_equal, p context: new Map(options.context || (parent_component ? parent_component.$$.context : [])), // everything else - callbacks: blank_object(), + callbacks: bind_events(options.props), dirty, skip_bound: false, root: options.target || parent_component.$$.root diff --git a/src/runtime/internal/lifecycle.ts b/src/runtime/internal/lifecycle.ts index bb3df3d29526..b696a368aa17 100644 --- a/src/runtime/internal/lifecycle.ts +++ b/src/runtime/internal/lifecycle.ts @@ -1,4 +1,4 @@ -import { custom_event } from './dom'; +import {custom_event} from './dom'; export let current_component; @@ -27,13 +27,12 @@ export function onDestroy(fn: () => any) { get_current_component().$$.on_destroy.push(fn); } -export function createEventDispatcher< - EventMap extends {} = any ->(): >(type: EventKey, detail?: EventMap[EventKey]) => void { +export function createEventDispatcher(): >(type: EventKey, detail?: EventMap[EventKey]) => void { const component = get_current_component(); return (type: string, detail?: any) => { const callbacks = component.$$.callbacks[type]; + const catchAllBinding = component.$$.callbacks[type]; if (callbacks) { // TODO are there situations where events could be dispatched @@ -43,6 +42,17 @@ export function createEventDispatcher< fn.call(component, event); }); } + + if (catchAllBinding) { + // in a server (non-DOM) environment? + try { + const event = custom_event(type, detail); + const data = catchAllBinding[1] && Object.prototype.hasOwnProperty.call(catchAllBinding[1], 'data') ? catchAllBinding[1].data : {}; + catchAllBinding[0].call(component, event, data); + } catch (e) { + console.warn(`A component was instantiated with invalid on:* configuration - ${e}`); + } + } }; } @@ -59,17 +69,12 @@ export function getAllContexts = Map>(): T { } export function hasContext(key): boolean { - return get_current_component().$$.context.has(key); + return get_current_component().$$.context.has(key); } -// TODO figure out if we still want to support +// TODO figure out if we still want to support - yes we do :) // shorthand events, or if we want to implement // a real bubbling mechanism export function bubble(component, event) { - const callbacks = component.$$.callbacks[event.type]; - - if (callbacks) { - // @ts-ignore - callbacks.slice().forEach(fn => fn.call(this, event)); - } + component.$$.ctx[0]['event:bindings'][event.type][0](component.$$.ctx[0]['event:bindings'][event.type][1]); }