Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

on:* #3349

Closed
wants to merge 15 commits into from
24 changes: 13 additions & 11 deletions src/compiler/compile/nodes/EventHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default class EventHandler extends Node {
constructor(component: Component, parent, template_scope, info) {
super(component, parent, template_scope, info);

this.name = info.name;
this.name = info.name !== '*' ? info.name : '$$any';
this.modifiers = new Set(info.modifiers);

if (info.expression) {
Expand All @@ -44,17 +44,19 @@ export default class EventHandler extends Node {
} else {
const name = component.get_unique_name(`${sanitize(this.name)}_handler`);

component.add_var({
name,
internal: true,
referenced: true
});
if (this.name !== '$$any') {
component.add_var({
name,
internal: true,
referenced: true
});

component.partly_hoisted.push(deindent`
function ${name}(event) {
@bubble($$self, event);
}
`);
component.partly_hoisted.push(deindent`
function ${name}(event) {
@bubble($$self, event);
}
`);
}

this.handler_name = name;
}
Expand Down
19 changes: 19 additions & 0 deletions src/compiler/compile/render_dom/Block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ export default class Block {
claim: CodeBuilder;
hydrate: CodeBuilder;
mount: CodeBuilder;
bubble: CodeBuilder;
measure: CodeBuilder;
fix: CodeBuilder;
animate: CodeBuilder;
Expand All @@ -45,6 +46,7 @@ export default class Block {
};

event_listeners: string[] = [];
any_event_elements: string[] = [];

maintain_context: boolean;
has_animation: boolean;
Expand Down Expand Up @@ -83,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(),
Expand Down Expand Up @@ -325,6 +328,22 @@ export default class Block {
`);
}

if (this.variables.size > 0) {
const listens = Array.from(this.variables.keys())
.filter(key => this.any_event_elements.includes(key))
.join(', ');

if (listens.length > 0) {
properties.add_block(deindent`
${method_name('bbl', 'bubble')}() {
let bubbles = [${listens}];
${this.builders.bubble}
return bubbles;
},
`);
}
}

if (this.has_intro_method || this.has_outro_method) {
if (this.builders.intro.is_empty()) {
properties.add_line(`i: @noop,`);
Expand Down
4 changes: 4 additions & 0 deletions src/compiler/compile/render_dom/wrappers/EachBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,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,
Expand Down
6 changes: 5 additions & 1 deletion src/compiler/compile/render_dom/wrappers/IfBlock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -507,7 +507,7 @@ export default class IfBlockWrapper extends Wrapper {
if (branch.snippet) {
block.builders.update.add_block(`if (${branch.dependencies.map(n => `changed.${n}`).join(' || ')}) ${branch.condition} = ${branch.snippet}`);
}

// no `p()` here — we don't want to update outroing nodes,
// as that will typically result in glitching
if (branch.block.has_outro_method) {
Expand Down Expand Up @@ -537,6 +537,10 @@ export default class IfBlockWrapper extends Wrapper {
`if (${branch.condition}) ${name}.p(changed, ctx);`
);
}

block.builders.bubble.add_line(
`if (${name}) bubbles.push(...${name}.bbl());`
);

block.builders.destroy.add_line(`${if_name}${name}.d(${detaching});`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ export default function add_event_handlers(
block.event_listeners.push(
`@listen(${target}, "${handler.name}", ${snippet}, ${opts_string})`
);
} else if (handler.name === '$$any') {
block.any_event_elements.push(target);
// This isn't required but listen is treeshaken otherwise
block.event_listeners.push(`@listen`);
} else {
block.event_listeners.push(
`@listen(${target}, "${handler.name}", ${snippet})`
Expand Down
1 change: 1 addition & 0 deletions src/runtime/ambient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ declare module '*.svelte' {
$set(props: Props): void;
$on<T = any>(event: string, callback: (event: CustomEvent<T>) => void): () => void;
$destroy(): void;
$bubble(): void;

[accessor: string]: any;
}
Expand Down
16 changes: 15 additions & 1 deletion src/runtime/internal/Component.ts
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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.$$;

Expand All @@ -43,6 +55,8 @@ export function mount_component(component, target, anchor) {
run_all(new_on_destroy);
}
component.$$.on_mount = [];

if (fragment.bbl) attach_any_listeners(component.$$);
});

after_update.forEach(add_render_callback);
Expand Down
4 changes: 3 additions & 1 deletion src/runtime/internal/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ function update($$) {
$$.fragment.p($$.dirty, $$.ctx);
$$.dirty = null;

$$.bubble && $$.bubble();

$$.after_update.forEach(add_render_callback);
}
}
}