diff --git a/src/compiler/compile/render_dom/Block.ts b/src/compiler/compile/render_dom/Block.ts index a9a0eee8c7..763fa4e208 100644 --- a/src/compiler/compile/render_dom/Block.ts +++ b/src/compiler/compile/render_dom/Block.ts @@ -35,6 +35,7 @@ export default class Block { claim: CodeBuilder; hydrate: CodeBuilder; mount: CodeBuilder; + bubble: CodeBuilder; measure: CodeBuilder; fix: CodeBuilder; animate: CodeBuilder; @@ -84,6 +85,7 @@ export default class Block { claim: new CodeBuilder(), hydrate: new CodeBuilder(), mount: new CodeBuilder(), + bubble: new CodeBuilder(), measure: new CodeBuilder(), fix: new CodeBuilder(), animate: new CodeBuilder(), @@ -334,7 +336,9 @@ export default class Block { if (listens.length > 0) { properties.add_block(deindent` ${method_name('bbl', 'bubble')}() { - return [listen, [${listens}]]; + let bubbles = [${listens}]; + ${this.builders.bubble} + return bubbles; }, `); } diff --git a/src/compiler/compile/render_dom/wrappers/EachBlock.ts b/src/compiler/compile/render_dom/wrappers/EachBlock.ts index 42792efce7..28f30cbc58 100644 --- a/src/compiler/compile/render_dom/wrappers/EachBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/EachBlock.ts @@ -218,6 +218,10 @@ export default class EachBlockWrapper extends Wrapper { `); } + block.builders.bubble.add_block(deindent` + for (#i = 0; #i < ${this.vars.data_length}; #i += 1) bubbles.push(...${this.vars.iterations}[#i].bbl()); + `); + if (needs_anchor) { block.add_element( update_anchor_node, diff --git a/src/compiler/compile/render_dom/wrappers/IfBlock.ts b/src/compiler/compile/render_dom/wrappers/IfBlock.ts index fe870df862..351d16e5c3 100644 --- a/src/compiler/compile/render_dom/wrappers/IfBlock.ts +++ b/src/compiler/compile/render_dom/wrappers/IfBlock.ts @@ -431,6 +431,10 @@ export default class IfBlockWrapper extends Wrapper { } `; + block.builders.bubble.add_line( + `if (${name}) bubbles.push(...${name}.bbl());` + ); + // no `p()` here — we don't want to update outroing nodes, // as that will typically result in glitching if (branch.block.has_outro_method) { diff --git a/src/runtime/ambient.ts b/src/runtime/ambient.ts index b094056c59..28e55686fe 100644 --- a/src/runtime/ambient.ts +++ b/src/runtime/ambient.ts @@ -13,6 +13,7 @@ declare module '*.svelte' { $set(props: Props): void; $on(event: string, callback: (event: CustomEvent) => void): () => void; $destroy(): void; + $bubble(): void; [accessor: string]: any; } diff --git a/src/runtime/internal/Component.ts b/src/runtime/internal/Component.ts index 79d89c2428..d61a04d72d 100644 --- a/src/runtime/internal/Component.ts +++ b/src/runtime/internal/Component.ts @@ -1,7 +1,7 @@ import { add_render_callback, flush, schedule_update, dirty_components } from './scheduler'; import { current_component, set_current_component } from './lifecycle'; import { blank_object, is_function, run, run_all, noop } from './utils'; -import { children } from './dom'; +import { children, listen } from './dom'; import { transition_in } from './transitions'; // eslint-disable-next-line @typescript-eslint/class-name-casing @@ -27,6 +27,18 @@ export function bind(component, name, callback) { callback(component.$$.ctx[name]); } +function attach_any_listeners($$) { + $$.bubble = () => Object.keys($$.callbacks).forEach(type => { + if ($$.ctx[`${type}_handler`]) return; + + $$.fragment.bbl().forEach(el => { + $$.callbacks[type].forEach(cb => listen(el, type, cb)); + }); + }); + + $$.bubble(); +} + export function mount_component(component, target, anchor) { const { fragment, on_mount, on_destroy, after_update } = component.$$; @@ -44,15 +56,7 @@ export function mount_component(component, target, anchor) { } component.$$.on_mount = []; - if (fragment.bbl) { - Object.keys(component.$$.callbacks).forEach(type => { - if (!component.$$.ctx[`${type}_handler`]) { - const [listen, els] = fragment.bbl(); - - els.forEach(el => component.$$.callbacks[type].forEach(cb => listen(el, type, cb))); - } - }); - } + if (fragment.bbl) attach_any_listeners(component.$$); }); after_update.forEach(add_render_callback); diff --git a/src/runtime/internal/scheduler.ts b/src/runtime/internal/scheduler.ts index e3d7181fcb..66ca63143c 100644 --- a/src/runtime/internal/scheduler.ts +++ b/src/runtime/internal/scheduler.ts @@ -76,6 +76,8 @@ function update($$) { $$.fragment.p($$.dirty, $$.ctx); $$.dirty = null; + $$.bubble && $$.bubble(); + $$.after_update.forEach(add_render_callback); } -} +} \ No newline at end of file