fix: invalidate props in `main_execution_context`

pull/8992/head
hackape 3 years ago
parent 0341e0b5d7
commit 841b641863

@ -38,7 +38,8 @@ export function invalidate(renderer, scope, node, names, main_execution_context
* @param {import('estree').Expression} [node] * @param {import('estree').Expression} [node]
*/ */
function get_invalidated(variable, node) { function get_invalidated(variable, node) {
if (main_execution_context && !variable.subscribable && variable.name[0] !== '$') { const is_props = !!variable.export_name;
if (main_execution_context && !is_props && !variable.subscribable && variable.name[0] !== '$') {
return node; return node;
} }
return renderer_invalidate(renderer, variable.name, undefined, main_execution_context); return renderer_invalidate(renderer, variable.name, undefined, main_execution_context);
@ -61,8 +62,9 @@ export function invalidate(renderer, scope, node, names, main_execution_context
return x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`; return x`@set_store_value(${head.name.slice(1)}, ${node}, ${head.name}, ${extra_args})`;
} }
const is_props = !!head.export_name;
let invalidate; let invalidate;
if (!main_execution_context) { if (!main_execution_context || is_props) {
const pass_value = const pass_value =
extra_args.length > 0 || extra_args.length > 0 ||
(node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') || (node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
@ -96,8 +98,9 @@ export function invalidate(renderer, scope, node, names, main_execution_context
*/ */
export function renderer_invalidate(renderer, name, value, main_execution_context = false) { export function renderer_invalidate(renderer, name, value, main_execution_context = false) {
const variable = renderer.component.var_lookup.get(name); const variable = renderer.component.var_lookup.get(name);
const is_props = variable && variable.export_name && !variable.module;
if (variable && variable.subscribable && (variable.reassigned || variable.export_name)) { if (variable && variable.subscribable && (variable.reassigned || variable.export_name)) {
if (main_execution_context) { if (main_execution_context && !is_props) {
return x`${`$$subscribe_${name}`}(${value || name})`; return x`${`$$subscribe_${name}`}(${value || name})`;
} else { } else {
const member = renderer.context_lookup.get(name); const member = renderer.context_lookup.get(name);
@ -124,6 +127,9 @@ export function renderer_invalidate(renderer, name, value, main_execution_contex
const member = renderer.context_lookup.get(name); const member = renderer.context_lookup.get(name);
return x`$$invalidate(${member.index}, ${value})`; return x`$$invalidate(${member.index}, ${value})`;
} }
} else if (main_execution_context && is_props) {
const member = renderer.context_lookup.get(name);
return x`$$invalidate(${member.index}, ${name})`;
} }
if (main_execution_context) return; if (main_execution_context) return;
// if this is a reactive declaration, invalidate dependencies recursively // if this is a reactive declaration, invalidate dependencies recursively

@ -24,7 +24,8 @@ export function bind(component, name, callback) {
const i = component.$$.props[name]; const i = component.$$.props[name];
if (i !== undefined) { if (i !== undefined) {
let dirty = false; let dirty = false;
if (component.$$.bound[i]) dirty = true; // special dirty flag for bind
if (component.$$.bound[i] === null) dirty = true;
component.$$.bound[i] = callback; component.$$.bound[i] = callback;
// first binding call, if child value is not yet dirty, skip to prevent unnecessary backflow // first binding call, if child value is not yet dirty, skip to prevent unnecessary backflow
callback(component.$$.ctx[i], /** skip_binding */ !dirty); callback(component.$$.ctx[i], /** skip_binding */ !dirty);
@ -127,10 +128,13 @@ export function init(
$$.ctx = instance $$.ctx = instance
? instance(component, options.props || {}, (i, ret, ...rest) => { ? instance(component, options.props || {}, (i, ret, ...rest) => {
const value = rest.length ? rest[0] : ret; const value = rest.length ? rest[0] : ret;
// `$$.bound[i] = null` as a special dirty flag to prevent unnecessary backflow, consumed in bind()
// only set at init phase during `instance()` call, and 1st `$$.update()` call before `ready`
if (!$$.ctx) $$.bound[i] = null;
if ($$.ctx && not_equal($$.ctx[i], ($$.ctx[i] = value))) { if ($$.ctx && not_equal($$.ctx[i], ($$.ctx[i] = value))) {
if (!$$.skip_bound && is_function($$.bound[i])) $$.bound[i](value); if (!$$.skip_bound && $$.bound[i]) $$.bound[i](value);
if (ready) make_dirty(component, i); if (ready) make_dirty(component, i);
else $$.bound[i] = true; // dirty flag consumed in bind() else $$.bound[i] = null;
} }
return ret; return ret;
}) })

Loading…
Cancel
Save