pull/4923/head
pushkine 5 years ago
parent c2a701fece
commit 2492441e89

@ -1,7 +1,7 @@
import Renderer from './Renderer'; import Renderer from './Renderer';
import Wrapper from './wrappers/shared/Wrapper'; import Wrapper from './wrappers/shared/Wrapper';
import { b, x } from 'code-red'; import { b, x } from 'code-red';
import { Node, Identifier, ArrayPattern } from 'estree'; import { Node, Identifier, ArrayPattern, Literal, CallExpression } from 'estree';
import { is_head } from './wrappers/shared/is_head'; import { is_head } from './wrappers/shared/is_head';
export interface BlockOptions { export interface BlockOptions {
@ -450,45 +450,51 @@ export default class Block {
: fn; : fn;
} }
render_listeners(chunk: string = '') { render_listeners() {
if (this.event_listeners.length > 0) { if (!this.event_listeners.length) return;
this.add_variable({ type: 'Identifier', name: '#mounted' }); const mounted = this.alias(`mounted`);
this.chunks.destroy.push(b`#mounted = false`); this.add_variable(mounted, x`false`);
const dispose: Identifier = { const mount = [];
type: 'Identifier', const destroy = [];
name: `#dispose${chunk}`
};
this.add_variable(dispose);
if (this.event_listeners.length === 1) { this.event_listeners.forEach((node) => {
this.chunks.mount.push( if (
b` isCallExpression(node) &&
if (!#mounted) { node.callee.type === "Identifier" &&
${dispose} = ${this.event_listeners[0]}; node.callee.name === "@listen"
#mounted = true; ) {
// b`@listen(ref, "type", args);`
const listener = this.get_unique_name(`${(node.arguments[1] as Literal).value}_listener`);
this.add_variable(listener);
mount.push(b`${listener} = ${node};`);
destroy.push(b`${listener}();`)
} else if (
node.type === "AssignmentExpression" &&
node.left.type === "Identifier" &&
node.left.name.endsWith("_action")
) {
// b`identifier = use_action(args);`
mount.push(node);
destroy.push(b`if (${node.left} && typeof ${node.left}.destroy === "function") ${node.left}.destroy();`)
} else {
throw new Error(`Forgot to specify logic for event_listener handling`);
} }
` });
);
this.chunks.destroy.push(
b`${dispose}();`
);
} else {
this.chunks.mount.push(b` this.chunks.mount.push(b`
if (!#mounted) { if (!${mounted}) {
${dispose} = [ ${mount}
${this.event_listeners} ${mounted} = true;
];
#mounted = true;
} }
`); `);
this.chunks.destroy.push( this.chunks.destroy.push(
b`${dispose}.forEach((#v) => #v());` b`
${destroy}
${mounted} = false;
`
); );
} }
} }
}
} const isCallExpression = (node): node is CallExpression => node.type === "CallExpression"

@ -111,7 +111,7 @@ export default function dom(
}` }`
: null; : null;
const k = set ? b`let #k;` : null const k = uses_$$ ? b`let #k;` : null
const accessors = []; const accessors = [];
const not_equal = component.component_options.immutable ? x`@not_equal` : x`@safe_not_equal`; const not_equal = component.component_options.immutable ? x`@not_equal` : x`@safe_not_equal`;

@ -43,7 +43,7 @@ export default class HeadWrapper extends Wrapper {
if (nodes && this.renderer.options.hydratable) { if (nodes && this.renderer.options.hydratable) {
block.chunks.claim.push( block.chunks.claim.push(
b`${nodes}.forEach(@detach);` b`for(let #i = 0;#i < ${nodes}.length; #i++) @detach(${nodes}[#i]);`
); );
} }
} }

@ -1,7 +1,6 @@
import { b, x } from 'code-red'; import { b, x } from 'code-red';
import Block from '../../Block'; import Block from '../../Block';
import Action from '../../../nodes/Action'; import Action from '../../../nodes/Action';
export default function add_actions( export default function add_actions(
block: Block, block: Block,
target: string, target: string,
@ -9,7 +8,6 @@ export default function add_actions(
) { ) {
actions.forEach(action => add_action(block, target, action)); actions.forEach(action => add_action(block, target, action));
} }
export function add_action(block: Block, target: string, action: Action) { export function add_action(block: Block, target: string, action: Action) {
const { expression } = action; const { expression } = action;
let snippet; let snippet;
@ -20,23 +18,20 @@ export function add_action(block: Block, target: string, action: Action) {
dependencies = expression.dynamic_dependencies(); dependencies = expression.dynamic_dependencies();
} }
const id = block.get_unique_name( const id = block.get_unique_name(`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`);
`${action.name.replace(/[^a-zA-Z0-9_$]/g, '_')}_action`
);
block.add_variable(id); block.add_variable(id);
const fn = block.renderer.reference(action.name); const fn = block.renderer.reference(action.name);
block.event_listeners.push( const subscriber = x`${id} = ${fn}.call(null, ${target}, ${snippet})`;
x`(${id} = ${fn}.call(null, ${target}, ${snippet})) && 'function' === typeof ${id}.destroy ? ${id}.destroy : @noop`
); block.event_listeners.push(subscriber);
if (dependencies && dependencies.length > 0) { if (dependencies && dependencies.length > 0) {
let condition = x`${id} && "function" === typeof ${id}.update`; let condition = x`${id} && "function" === typeof ${id}.update`;
if (dependencies.length > 0) { if (dependencies.length > 0) {
condition = x`${condition} && ${block.renderer.dirty(dependencies)}`; condition = x`${block.renderer.dirty(dependencies)} && ${condition}`;
} }
block.chunks.update.push( block.chunks.update.push(

Loading…
Cancel
Save