pull/3539/head
Rich Harris 6 years ago
parent 6514b142dc
commit af1057b4a3

10
package-lock.json generated

@ -330,11 +330,6 @@
"integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
"dev": true "dev": true
}, },
"astring": {
"version": "github:Rich-Harris/astring#ff83f5e4e75b304cdd428ada4a71372276b0084d",
"from": "github:Rich-Harris/astring#generic-handler",
"dev": true
},
"async-limiter": { "async-limiter": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz", "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.0.tgz",
@ -513,13 +508,16 @@
"dev": true, "dev": true,
"requires": { "requires": {
"acorn": "^7.0.0", "acorn": "^7.0.0",
"astring": "github:Rich-Harris/astring#ff83f5e4e75b304cdd428ada4a71372276b0084d",
"estree-walker": "^0.6.1", "estree-walker": "^0.6.1",
"is-reference": "^1.1.3", "is-reference": "^1.1.3",
"periscopic": "^1.0.0", "periscopic": "^1.0.0",
"source-map": "^0.7.3" "source-map": "^0.7.3"
}, },
"dependencies": { "dependencies": {
"astring": {
"version": "github:Rich-Harris/astring#ff83f5e4e75b304cdd428ada4a71372276b0084d",
"from": "github:Rich-Harris/astring#ff83f5e4e75b304cdd428ada4a71372276b0084d"
},
"estree-walker": { "estree-walker": {
"version": "0.6.1", "version": "0.6.1",
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz",

@ -912,11 +912,13 @@ export default class Component {
computed: false, computed: false,
kind: 'init', kind: 'init',
key: declarator.id, key: declarator.id,
value: { value: declarator.init
? {
type: 'AssignmentPattern', type: 'AssignmentPattern',
left: declarator.id, left: declarator.id,
right: declarator.init right: declarator.init
} }
: declarator.id
}] }]
}; };
@ -1228,7 +1230,7 @@ export default class Component {
} }
qualify(name) { qualify(name) {
if (name === `$$props`) return `#ctx.$$props`; if (name === `$$props`) return x`#ctx.$$props`;
const variable = this.var_lookup.get(name); const variable = this.var_lookup.get(name);
@ -1238,7 +1240,7 @@ export default class Component {
if (variable.hoistable) return name; if (variable.hoistable) return name;
return `#ctx.${name}`; return x`#ctx.${name}`;
} }
warn_if_undefined(name: string, node, template_scope: TemplateScope) { warn_if_undefined(name: string, node, template_scope: TemplateScope) {

@ -173,7 +173,8 @@ function cjs(
shorthand: false, shorthand: false,
computed: false, computed: false,
key: s.imported || { type: 'Identifier', name: 'default' }, key: s.imported || { type: 'Identifier', name: 'default' },
value: s.local value: s.local,
kind: 'init'
})) }))
}, },
init: x`require("${edit_source(node.source.value, sveltePath)}")` init: x`require("${edit_source(node.source.value, sveltePath)}")`

@ -4,6 +4,7 @@ import Expression from './shared/Expression';
import Component from '../Component'; import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import {dimensions} from "../../utils/patterns"; import {dimensions} from "../../utils/patterns";
import { x } from 'code-red';
// TODO this should live in a specific binding // TODO this should live in a specific binding
const read_only_media_attributes = new Set([ const read_only_media_attributes = new Set([
@ -68,8 +69,8 @@ export default class Binding extends Node {
if (!this.expression.node.computed) prop = `'${prop}'`; if (!this.expression.node.computed) prop = `'${prop}'`;
obj = `[✂${this.expression.node.object.start}-${this.expression.node.object.end}✂]`; obj = `[✂${this.expression.node.object.start}-${this.expression.node.object.end}✂]`;
} else { } else {
obj = '#ctx'; obj = x`#ctx`;
prop = `'${name}'`; prop = x`'${name}'`;
} }
this.obj = obj; this.obj = obj;

@ -1,7 +1,7 @@
import Node from './shared/Node'; import Node from './shared/Node';
import Expression from './shared/Expression'; import Expression from './shared/Expression';
import Component from '../Component'; import Component from '../Component';
import { b } from 'code-red'; import { b, x } from 'code-red';
import Block from '../render_dom/Block'; import Block from '../render_dom/Block';
import { sanitize } from '../../utils/names'; import { sanitize } from '../../utils/names';
import { Identifier } from '../../interfaces'; import { Identifier } from '../../interfaces';
@ -63,9 +63,11 @@ export default class EventHandler extends Node {
// TODO move this? it is specific to render-dom // TODO move this? it is specific to render-dom
render(block: Block) { render(block: Block) {
if (this.expression) this.expression.manipulate(block); if (this.expression) {
return this.expression.manipulate(block);
}
// this.component.add_reference(this.handler_name); // this.component.add_reference(this.handler_name);
return `#ctx.${this.handler_name}`; return x`#ctx.${this.handler_name}`;
} }
} }

@ -57,7 +57,7 @@ export default class Block {
destroy: Node[]; destroy: Node[];
}; };
event_listeners: string[] = []; event_listeners: Node[] = [];
maintain_context: boolean; maintain_context: boolean;
has_animation: boolean; has_animation: boolean;
@ -430,7 +430,7 @@ export default class Block {
} else { } else {
this.chunks.hydrate.push(b` this.chunks.hydrate.push(b`
${dispose} = [ ${dispose} = [
${this.event_listeners.join(',\n')} ${this.event_listeners}
]; ];
`); `);

@ -1,5 +1,4 @@
import { b, x } from 'code-red'; import { b, x } from 'code-red';
import deindent from '../utils/deindent';
import { stringify, escape } from '../utils/stringify'; import { stringify, escape } from '../utils/stringify';
import Component from '../Component'; import Component from '../Component';
import Renderer from './Renderer'; import Renderer from './Renderer';
@ -99,44 +98,59 @@ export default function dom(
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`;
let dev_props_check; let inject_state; let capture_state; let dev_props_check; let inject_state; let capture_state;
props.forEach(x => { props.forEach(prop => {
const variable = component.var_lookup.get(x.name); const variable = component.var_lookup.get(prop.name);
if (!variable.writable || component.component_options.accessors) { if (!variable.writable || component.component_options.accessors) {
accessors.push(deindent` accessors.push({
get ${x.export_name}() { type: 'MethodDefinition',
return ${x.hoistable ? x.name : 'this.$$.ctx.' + x.name}; kind: 'get',
} key: { type: 'Identifier', name: prop.export_name },
`); value: x`function() {
return ${prop.hoistable ? prop.name : x`this.$$.ctx.${prop.name}`}
}`
});
} else if (component.compile_options.dev) { } else if (component.compile_options.dev) {
accessors.push(deindent` accessors.push({
get ${x.export_name}() { type: 'MethodDefinition',
kind: 'get',
key: { type: 'Identifier', name: prop.export_name },
value: x`function() {
throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'"); throw new @_Error("<${component.tag}>: Props cannot be read directly from the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
} }`
`); });
} }
if (component.component_options.accessors) { if (component.component_options.accessors) {
if (variable.writable && !renderer.readonly.has(x.name)) { if (variable.writable && !renderer.readonly.has(prop.name)) {
accessors.push(deindent` accessors.push({
set ${x.export_name}(${x.name}) { type: 'MethodDefinition',
this.$set({ ${x.name === x.export_name ? x.name : `${x.export_name}: ${x.name}`} }); kind: 'set',
key: { type: 'Identifier', name: prop.export_name },
value: x`function(${prop.name}) {
this.$set({ ${prop.export_name}: ${prop.name} });
@flush(); @flush();
} }`
`); });
} else if (component.compile_options.dev) { } else if (component.compile_options.dev) {
accessors.push(deindent` accessors.push({
set ${x.export_name}(value) { type: 'MethodDefinition',
throw new @_Error("<${component.tag}>: Cannot set read-only property '${x.export_name}'"); kind: 'set',
} key: { type: 'Identifier', name: prop.export_name },
`); value: x`function(value) {
throw new @_Error("<${component.tag}>: Cannot set read-only property '${prop.export_name}'");
}`
});
} }
} else if (component.compile_options.dev) { } else if (component.compile_options.dev) {
accessors.push(deindent` accessors.push({
set ${x.export_name}(value) { type: 'MethodDefinition',
kind: 'set',
key: { type: 'Identifier', name: prop.export_name },
value: x`function(value) {
throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'"); throw new @_Error("<${component.tag}>: Props cannot be set directly on the component instance unless compiling with 'accessors: true' or '<svelte:options accessors/>'");
} }`
`); });
} }
}); });
@ -204,7 +218,7 @@ export default function dom(
// onto the initial function call // onto the initial function call
const names = new Set(extract_names(assignee)); const names = new Set(extract_names(assignee));
invalidate(component, scope, node, names); this.replace(invalidate(component, scope, node, names));
} }
} }
}); });
@ -405,7 +419,7 @@ export default function dom(
}); });
if (options.customElement) { if (options.customElement) {
body.push(b` const declaration = b`
class ${name} extends @SvelteElement { class ${name} extends @SvelteElement {
constructor(options) { constructor(options) {
super(); super();
@ -428,15 +442,24 @@ export default function dom(
}`} }`}
} }
} }
}
`[0];
${props.length > 0 && deindent` if (props.length > 0) {
static get observedAttributes() { declaration.body.body.push({
return ${JSON.stringify(props.map(x => x.export_name))}; type: 'MethodDefinition',
}`} kind: 'get',
static: true,
${body.length > 0 && body.join('\n\n')} key: { type: 'Identifier', name: 'observedAttributes' },
value: x`function() {
return [${props.map(prop => x`"${prop.export_name}"`)}];
}`
})
} }
`);
declaration.body.body.push(...accessors);
body.push(declaration);
if (component.tag != null) { if (component.tag != null) {
body.push(b` body.push(b`
@ -449,9 +472,7 @@ export default function dom(
name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent' name: options.dev ? '@SvelteComponentDev' : '@SvelteComponent'
}; };
// TODO add accessors const declaration = b`
body.push(b`
class ${name} extends ${superclass} { class ${name} extends ${superclass} {
constructor(options) { constructor(options) {
super(${options.dev && `options`}); super(${options.dev && `options`});
@ -462,7 +483,11 @@ export default function dom(
${dev_props_check} ${dev_props_check}
} }
} }
`); `[0];
declaration.body.body.push(...accessors);
body.push(declaration);
} }
return flatten(body, []); return flatten(body, []);

@ -63,7 +63,7 @@ export default class DebugTagWrapper extends Wrapper {
// block.chunks.update.push(b` // block.chunks.update.push(b`
// if (${condition}) { // if (${condition}) {
// const { ${ctx_identifiers} } = ctx; // const { ${ctx_identifiers} } = #ctx;
// @_console.${log}({ ${logged_identifiers} }); // @_console.${log}({ ${logged_identifiers} });
// debugger; // debugger;
// } // }
@ -71,7 +71,7 @@ export default class DebugTagWrapper extends Wrapper {
// block.chunks.create.push(b` // block.chunks.create.push(b`
// { // {
// const { ${ctx_identifiers} } = ctx; // const { ${ctx_identifiers} } = #ctx;
// @_console.${log}({ ${logged_identifiers} }); // @_console.${log}({ ${logged_identifiers} });
// debugger; // debugger;
// } // }

@ -125,11 +125,11 @@ export default class BindingWrapper {
const binding_group = get_binding_group(parent.renderer, this.node.expression.node); const binding_group = get_binding_group(parent.renderer, this.node.expression.node);
block.chunks.hydrate.push( block.chunks.hydrate.push(
b`ctx.$$binding_groups[${binding_group}].push(${parent.var});` b`#ctx.$$binding_groups[${binding_group}].push(${parent.var});`
); );
block.chunks.destroy.push( block.chunks.destroy.push(
b`ctx.$$binding_groups[${binding_group}].splice(ctx.$$binding_groups[${binding_group}].indexOf(${parent.var}), 1);` b`#ctx.$$binding_groups[${binding_group}].splice(#ctx.$$binding_groups[${binding_group}].indexOf(${parent.var}), 1);`
); );
break; break;
} }

@ -480,21 +480,21 @@ export default class ElementWrapper extends Wrapper {
${animation_frame} = @raf(${handler}); ${animation_frame} = @raf(${handler});
${needs_lock && `${lock} = true;`} ${needs_lock && `${lock} = true;`}
} }
ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', ctx' : ''}); #ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', #ctx' : ''});
} }
`); `);
} else { } else {
block.chunks.init.push(b` block.chunks.init.push(b`
function ${handler}() { function ${handler}() {
${needs_lock && `${lock} = true;`} ${needs_lock && `${lock} = true;`}
ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', ctx' : ''}); #ctx.${handler}.call(${this.var}${contextual_dependencies.size > 0 ? ', #ctx' : ''});
} }
`); `);
} }
callee = handler; callee = handler;
} else { } else {
callee = `ctx.${handler}`; callee = x`#ctx.${handler}`;
} }
this.renderer.component.partly_hoisted.push(b` this.renderer.component.partly_hoisted.push(b`
@ -519,7 +519,7 @@ export default class ElementWrapper extends Wrapper {
); );
} else { } else {
block.event_listeners.push( block.event_listeners.push(
`@listen(${this.var}, "${name}", ${callee})` x`@listen(${this.var}, "${name}", ${callee})`
); );
} }
}); });

@ -250,14 +250,14 @@ export default class InlineComponentWrapper extends Wrapper {
} }
if (non_let_dependencies.length > 0) { if (non_let_dependencies.length > 0) {
updates.push(`if (${non_let_dependencies.map(n => `changed.${n}`).join(' || ')}) ${name_changes}.$$scope = { changed, ctx };`); updates.push(`if (${non_let_dependencies.map(n => `changed.${n}`).join(' || ')}) ${name_changes}.$$scope = { changed: #changed, ctx: #ctx };`);
} }
const munged_bindings = this.node.bindings.map(binding => { const munged_bindings = this.node.bindings.map(binding => {
component.has_reactive_assignments = true; component.has_reactive_assignments = true;
if (binding.name === 'this') { if (binding.name === 'this') {
return bind_this(component, block, binding, this.var.name); return bind_this(component, block, binding, this.var);
} }
const id = component.get_unique_name(`${this.var}_${binding.name}_binding`); const id = component.get_unique_name(`${this.var}_${binding.name}_binding`);
@ -306,7 +306,7 @@ export default class InlineComponentWrapper extends Wrapper {
block.chunks.init.push(b` block.chunks.init.push(b`
function ${name}(${value}) { function ${name}(${value}) {
ctx.${name}.call(null, ${value}, ctx); #ctx.${name}.call(null, ${value}, #ctx);
${updating} = true; ${updating} = true;
@add_flush_callback(() => ${updating} = false); @add_flush_callback(() => ${updating} = false);
} }
@ -316,7 +316,7 @@ export default class InlineComponentWrapper extends Wrapper {
} else { } else {
block.chunks.init.push(b` block.chunks.init.push(b`
function ${id}(${value}) { function ${id}(${value}) {
ctx.${name}.call(null, ${value}); #ctx.${name}.call(null, ${value});
${updating} = true; ${updating} = true;
@add_flush_callback(() => ${updating} = false); @add_flush_callback(() => ${updating} = false);
} }
@ -337,7 +337,7 @@ export default class InlineComponentWrapper extends Wrapper {
const munged_handlers = this.node.handlers.map(handler => { const munged_handlers = this.node.handlers.map(handler => {
let snippet = handler.render(block); let snippet = handler.render(block);
if (handler.modifiers.has('once')) snippet = `@once(${snippet})`; if (handler.modifiers.has('once')) snippet = x`@once(${snippet})`;
return `${name}.$on("${handler.name}", ${snippet});`; return `${name}.$on("${handler.name}", ${snippet});`;
}); });
@ -351,7 +351,7 @@ export default class InlineComponentWrapper extends Wrapper {
block.chunks.init.push(b` block.chunks.init.push(b`
var ${switch_value} = ${snippet}; var ${switch_value} = ${snippet};
function ${switch_props}(ctx) { function ${switch_props}(#ctx) {
${(this.node.attributes.length || this.node.bindings.length) && b` ${(this.node.attributes.length || this.node.bindings.length) && b`
${props && `let ${props} = ${attribute_object};`}`} ${props && `let ${props} = ${attribute_object};`}`}
${statements} ${statements}
@ -359,7 +359,7 @@ export default class InlineComponentWrapper extends Wrapper {
} }
if (${switch_value}) { if (${switch_value}) {
var ${name} = new ${switch_value}(${switch_props}(ctx)); var ${name} = new ${switch_value}(${switch_props}(#ctx));
${munged_bindings} ${munged_bindings}
${munged_handlers} ${munged_handlers}
@ -403,7 +403,7 @@ export default class InlineComponentWrapper extends Wrapper {
} }
if (${switch_value}) { if (${switch_value}) {
${name} = new ${switch_value}(${switch_props}(ctx)); ${name} = new ${switch_value}(${switch_props}(#ctx));
${munged_bindings} ${munged_bindings}
${munged_handlers} ${munged_handlers}

@ -110,8 +110,8 @@ export default class SlotWrapper extends Wrapper {
const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`); const slot_definition = block.get_unique_name(`${sanitize(slot_name)}_slot_template`);
block.chunks.init.push(b` block.chunks.init.push(b`
const ${slot_definition} = ctx.$$slots${quote_prop_if_necessary(slot_name)}; const ${slot_definition} = #ctx.$$slots${quote_prop_if_necessary(slot_name)};
const ${slot} = @create_slot(${slot_definition}, ctx, ${get_slot_context}); const ${slot} = @create_slot(${slot_definition}, #ctx, ${get_slot_context});
`); `);
const mount_before = block.chunks.mount.slice(); const mount_before = block.chunks.mount.slice();
@ -175,8 +175,8 @@ export default class SlotWrapper extends Wrapper {
block.chunks.update.push(b` block.chunks.update.push(b`
if (${slot} && ${slot}.p && ${update_conditions}) { if (${slot} && ${slot}.p && ${update_conditions}) {
${slot}.p( ${slot}.p(
@get_slot_changes(${slot_definition}, ctx, changed, ${get_slot_changes}), @get_slot_changes(${slot_definition}, #ctx, changed, ${get_slot_changes}),
@get_slot_context(${slot_definition}, ctx, ${get_slot_context}) @get_slot_context(${slot_definition}, #ctx, ${get_slot_context})
); );
} }
`); `);

@ -82,13 +82,12 @@ export default class WindowWrapper extends Wrapper {
block.add_variable(clear_scrolling, x`() => { ${scrolling} = false }`); block.add_variable(clear_scrolling, x`() => { ${scrolling} = false }`);
block.add_variable(scrolling_timeout); block.add_variable(scrolling_timeout);
const condition = [ const condition = bindings.scrollX && bindings.scrollY
bindings.scrollX && `"${bindings.scrollX}" in this._state`, ? x`"${bindings.scrollX}" in this._state || "${bindings.scrollY}" in this._state`
bindings.scrollY && `"${bindings.scrollY}" in this._state` : x`"${bindings.scrollX || bindings.scrollY}" in this._state`;
].filter(Boolean).join(' || ');
const scrollX = bindings.scrollX && `this._state.${bindings.scrollX}`; const scrollX = bindings.scrollX && x`this._state.${bindings.scrollX}`;
const scrollY = bindings.scrollY && `this._state.${bindings.scrollY}`; const scrollY = bindings.scrollY && x`this._state.${bindings.scrollY}`;
renderer.meta_bindings.push(b` renderer.meta_bindings.push(b`
if (${condition}) { if (${condition}) {
@ -98,12 +97,12 @@ export default class WindowWrapper extends Wrapper {
${scrollY && `${scrollY} = @_window.pageYOffset;`} ${scrollY && `${scrollY} = @_window.pageYOffset;`}
`); `);
block.event_listeners.push(b` block.event_listeners.push(x`
@listen(@_window, "${event}", () => { @listen(@_window, "${event}", () => {
${scrolling} = true; ${scrolling} = true;
@_clearTimeout(${scrolling_timeout}); @_clearTimeout(${scrolling_timeout});
${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100); ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
ctx.${id}(); #ctx.${id}();
}) })
`); `);
} else { } else {
@ -113,8 +112,8 @@ export default class WindowWrapper extends Wrapper {
); );
}); });
block.event_listeners.push(b` block.event_listeners.push(x`
@listen(@_window, "${event}", ctx.${id}) @listen(@_window, "${event}", #ctx.${id})
`); `);
} }
@ -131,7 +130,7 @@ export default class WindowWrapper extends Wrapper {
`); `);
block.chunks.init.push(b` block.chunks.init.push(b`
@add_render_callback(ctx.${id}); @add_render_callback(#ctx.${id});
`); `);
component.has_reactive_assignments = true; component.has_reactive_assignments = true;
@ -148,9 +147,9 @@ export default class WindowWrapper extends Wrapper {
${scrolling} = true; ${scrolling} = true;
@_clearTimeout(${scrolling_timeout}); @_clearTimeout(${scrolling_timeout});
@_scrollTo(${ @_scrollTo(${
bindings.scrollX ? `ctx.${bindings.scrollX}` : `@_window.pageXOffset` bindings.scrollX ? `#ctx.${bindings.scrollX}` : `@_window.pageXOffset`
}, ${ }, ${
bindings.scrollY ? `ctx.${bindings.scrollY}` : `@_window.pageYOffset` bindings.scrollY ? `#ctx.${bindings.scrollY}` : `@_window.pageYOffset`
}); });
${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100); ${scrolling_timeout} = @_setTimeout(${clear_scrolling}, 100);
} }
@ -175,12 +174,12 @@ export default class WindowWrapper extends Wrapper {
`); `);
block.chunks.init.push(b` block.chunks.init.push(b`
@add_render_callback(ctx.${id}); @add_render_callback(#ctx.${id});
`); `);
block.event_listeners.push( block.event_listeners.push(
`@listen(@_window, "online", ctx.${id})`, x`@listen(@_window, "online", #ctx.${id})`,
`@listen(@_window, "offline", ctx.${id})` x`@listen(@_window, "offline", #ctx.${id})`
); );
component.has_reactive_assignments = true; component.has_reactive_assignments = true;

@ -1,5 +1,6 @@
import Block from '../../Block'; import Block from '../../Block';
import EventHandler from '../../../nodes/EventHandler'; import EventHandler from '../../../nodes/EventHandler';
import { x } from 'code-red';
export default function add_event_handlers( export default function add_event_handlers(
block: Block, block: Block,
@ -8,35 +9,37 @@ export default function add_event_handlers(
) { ) {
handlers.forEach(handler => { handlers.forEach(handler => {
let snippet = handler.render(block); let snippet = handler.render(block);
if (handler.modifiers.has('preventDefault')) snippet = `@prevent_default(${snippet})`; if (handler.modifiers.has('preventDefault')) snippet = x`@prevent_default(${snippet})`;
if (handler.modifiers.has('stopPropagation')) snippet = `@stop_propagation(${snippet})`; if (handler.modifiers.has('stopPropagation')) snippet = x`@stop_propagation(${snippet})`;
if (handler.modifiers.has('self')) snippet = `@self(${snippet})`; if (handler.modifiers.has('self')) snippet = x`@self(${snippet})`;
let opts_string = ''; // let opts_string = '';
if (block.renderer.options.dev) { // if (block.renderer.options.dev) {
if (handler.modifiers.has('stopPropagation')) { // if (handler.modifiers.has('stopPropagation')) {
opts_string = ', true'; // opts_string = ', true';
} // }
if (handler.modifiers.has('preventDefault')) { // if (handler.modifiers.has('preventDefault')) {
opts_string = ', true' + opts_string; // opts_string = ', true' + opts_string;
} else if (opts_string) { // } else if (opts_string) {
opts_string = ', false' + opts_string; // opts_string = ', false' + opts_string;
} // }
} // }
const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod)); // const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod));
if (opts.length) { // if (opts.length) {
opts_string = (opts.length === 1 && opts[0] === 'capture') // opts_string = (opts.length === 1 && opts[0] === 'capture')
? ', true' // ? ', true'
: `, { ${opts.map(opt => `${opt}: true`).join(', ')} }`; // : `, { ${opts.map(opt => `${opt}: true`).join(', ')} }`;
} else if (opts_string) { // } else if (opts_string) {
opts_string = ', false' + opts_string; // opts_string = ', false' + opts_string;
} // }
// TODO modifiers
block.event_listeners.push( block.event_listeners.push(
`@listen(${target}, "${handler.name}", ${snippet}${opts_string})` x`@listen(${target}, "${handler.name}", ${snippet})`
); );
}); });
} }

@ -5,8 +5,8 @@ import Block from '../../Block';
import Binding from '../../../nodes/Binding'; import Binding from '../../../nodes/Binding';
import { Identifier } from '../../../../interfaces'; import { Identifier } from '../../../../interfaces';
export default function bind_this(component: Component, block: Block, binding: Binding, variable: string) { export default function bind_this(component: Component, block: Block, binding: Binding, variable: Identifier) {
const fn = component.get_unique_name(`${variable}_binding`); const fn = component.get_unique_name(`${variable.name}_binding`);
component.add_var({ component.add_var({
name: fn.name, name: fn.name,
@ -56,18 +56,18 @@ export default function bind_this(component: Component, block: Block, binding: B
for (const arg of contextual_dependencies) { for (const arg of contextual_dependencies) {
const id: Identifier = { type: 'Identifier', name: arg }; const id: Identifier = { type: 'Identifier', name: arg };
args.push(id); args.push(id);
block.add_variable(id, x`ctx.${id}`); block.add_variable(id, x`#ctx.${id}`);
} }
const assign = block.get_unique_name(`assign_${variable}`); const assign = block.get_unique_name(`assign_${variable}`);
const unassign = block.get_unique_name(`unassign_${variable}`); const unassign = block.get_unique_name(`unassign_${variable}`);
block.chunks.init.push(b` block.chunks.init.push(b`
const ${assign} = () => ctx.${fn}(${[variable].concat(args).join(', ')}); const ${assign} = () => #ctx.${fn}(${[variable].concat(args).join(', ')});
const ${unassign} = () => ctx.${fn}(${['null'].concat(args).join(', ')}); const ${unassign} = () => #ctx.${fn}(${['null'].concat(args).join(', ')});
`); `);
const condition = Array.from(contextual_dependencies).map(name => `${name} !== ctx.${name}`).join(' || '); const condition = Array.from(contextual_dependencies).map(name => `${name} !== #ctx.${name}`).join(' || ');
// we push unassign and unshift assign so that references are // we push unassign and unshift assign so that references are
// nulled out before they're created, to avoid glitches // nulled out before they're created, to avoid glitches
@ -75,7 +75,7 @@ export default function bind_this(component: Component, block: Block, binding: B
block.chunks.update.push(b` block.chunks.update.push(b`
if (${condition}) { if (${condition}) {
${unassign}(); ${unassign}();
${args.map(a => `${a} = ctx.${a}`).join(', ')}; ${args.map(a => `${a} = #ctx.${a}`).join(', ')};
${assign}(); ${assign}();
}` }`
); );
@ -92,6 +92,6 @@ export default function bind_this(component: Component, block: Block, binding: B
} }
`); `);
block.chunks.destroy.push(b`ctx.${fn}(null);`); block.chunks.destroy.push(b`#ctx.${fn}(null);`);
return b`ctx.${fn}(${variable});`; return b`#ctx.${fn}(${variable});`;
} }

@ -85,7 +85,7 @@ export default function(node: Element, renderer: Renderer, options: RenderOption
const class_expression = node.classes.map((class_directive: Class) => { const class_expression = node.classes.map((class_directive: Class) => {
const { expression, name } = class_directive; const { expression, name } = class_directive;
const snippet = expression ? snip(expression) : `ctx${quote_prop_if_necessary(name)}`; const snippet = expression ? snip(expression) : `#ctx${quote_prop_if_necessary(name)}`;
return `${snippet} ? "${name}" : ""`; return `${snippet} ? "${name}" : ""`;
}).join(', '); }).join(', ');

@ -55,7 +55,10 @@ export function invalidate(component: Component, scope: Scope, node: Node, names
); );
if (pass_value) { if (pass_value) {
extra_args.unshift(head); extra_args.unshift({
type: 'Identifier',
name: head
});
} }
return x`$$invalidate("${head}", ${node}, ${extra_args})`; return x`$$invalidate("${head}", ${node}, ${extra_args})`;

@ -102,7 +102,6 @@ export function init(component, options, instance, create_fragment, not_equal, p
$$.ctx = instance $$.ctx = instance
? instance(component, props, (key, ret, value = ret) => { ? instance(component, props, (key, ret, value = ret) => {
console.log(`invalidating`, key, ret, value);
if ($$.ctx && not_equal($$.ctx[key], $$.ctx[key] = value)) { if ($$.ctx && not_equal($$.ctx[key], $$.ctx[key] = value)) {
if ($$.bound[key]) $$.bound[key](value); if ($$.bound[key]) $$.bound[key](value);
if (ready) make_dirty(component, key); if (ready) make_dirty(component, key);

@ -4,7 +4,7 @@
function foo(node) { function foo(node) {
const handler = () => { const handler = () => {
x += 1; x += 1;
} };
node.addEventListener('click', handler); node.addEventListener('click', handler);
handler(); handler();

@ -3,7 +3,7 @@ export default {
<button>action</button> <button>action</button>
`, `,
async test({ assert, component, target, window }) { async test({ assert, target, window }) {
const button = target.querySelector('button'); const button = target.querySelector('button');
const enter = new window.MouseEvent('mouseenter'); const enter = new window.MouseEvent('mouseenter');
const leave = new window.MouseEvent('mouseleave'); const leave = new window.MouseEvent('mouseleave');

Loading…
Cancel
Save