pull/9813/head
Rich Harris 3 years ago
parent 8c934ffb5b
commit 5c44d72dba

@ -353,67 +353,53 @@ export function serialize_hoistable_params(node, context) {
}
/**
*
* @param {import('#compiler').Binding} binding
* @param {import('./types').ComponentClientTransformState} state
* @param {string} name
* @param {import('estree').Expression | null} [default_value]
* @param {import('estree').Expression | null} [initial]
* @returns
*/
export function get_props_method(binding, state, name, default_value) {
export function get_prop_source(state, name, initial) {
/** @type {import('estree').Expression[]} */
const args = [b.id('$$props'), b.literal(name)];
// Use $.prop_source in the following cases:
// - accessors/mutated: needs to be able to set the prop value from within
// - default value: we set the fallback value only initially, and it's not possible to know this timing in $.prop
const needs_source =
default_value ||
state.analysis.accessors ||
(state.analysis.immutable ? binding.reassigned : binding.mutated);
let flags = 0;
if (needs_source) {
let flags = 0;
/** @type {import('estree').Expression | undefined} */
let arg;
if (state.analysis.immutable) {
flags |= PROPS_IS_IMMUTABLE;
}
if (state.analysis.immutable) {
flags |= PROPS_IS_IMMUTABLE;
}
if (state.analysis.runes) {
flags |= PROPS_IS_RUNES;
}
if (state.analysis.runes) {
flags |= PROPS_IS_RUNES;
}
/** @type {import('estree').Expression | undefined} */
let arg;
if (default_value) {
// To avoid eagerly evaluating the right-hand-side, we wrap it in a thunk if necessary
if (is_simple_expression(default_value)) {
arg = default_value;
if (initial) {
// To avoid eagerly evaluating the right-hand-side, we wrap it in a thunk if necessary
if (is_simple_expression(initial)) {
arg = initial;
} else {
if (
initial.type === 'CallExpression' &&
initial.callee.type === 'Identifier' &&
initial.arguments.length === 0
) {
arg = initial.callee;
} else {
if (
default_value.type === 'CallExpression' &&
default_value.callee.type === 'Identifier' &&
default_value.arguments.length === 0
) {
arg = default_value.callee;
} else {
arg = b.thunk(default_value);
}
flags |= PROPS_CALL_DEFAULT_VALUE;
arg = b.thunk(initial);
}
}
if (flags || arg) {
args.push(b.literal(flags));
if (arg) args.push(arg);
flags |= PROPS_CALL_DEFAULT_VALUE;
}
}
return b.call('$.prop_source', ...args);
if (flags || arg) {
args.push(b.literal(flags));
if (arg) args.push(arg);
}
return b.call('$.prop', ...args);
return b.call('$.prop_source', ...args);
}
/**

@ -1,7 +1,7 @@
import { is_hoistable_function } from '../../utils.js';
import * as b from '../../../../utils/builders.js';
import { extract_paths } from '../../../../utils/ast.js';
import { create_state_declarators, get_props_method, serialize_get_binding } from '../utils.js';
import { create_state_declarators, get_prop_source, serialize_get_binding } from '../utils.js';
/** @type {import('../types.js').ComponentVisitors} */
export const javascript_visitors_legacy = {
@ -55,7 +55,7 @@ export const javascript_visitors_legacy = {
b.declarator(
path.node,
binding.kind === 'prop'
? get_props_method(binding, state, binding.prop_alias ?? name, value)
? get_prop_source(state, binding.prop_alias ?? name, value)
: value
)
);
@ -75,8 +75,7 @@ export const javascript_visitors_legacy = {
declarations.push(
b.declarator(
declarator.id,
get_props_method(
binding,
get_prop_source(
state,
binding.prop_alias ?? declarator.id.name,
declarator.init &&

@ -2,7 +2,7 @@ import { get_rune } from '../../../scope.js';
import { is_hoistable_function } from '../../utils.js';
import * as b from '../../../../utils/builders.js';
import * as assert from '../../../../utils/assert.js';
import { create_state_declarators, get_props_method, should_proxy } from '../utils.js';
import { create_state_declarators, get_prop_source, should_proxy } from '../utils.js';
import { unwrap_ts_expression } from '../../../../utils/ast.js';
/** @type {import('../types.js').ComponentVisitors} */
@ -185,7 +185,7 @@ export const javascript_visitors_runes = {
const binding = /** @type {import('#compiler').Binding} */ (state.scope.get(id.name));
if (binding.reassigned || state.analysis.accessors || initial) {
declarations.push(b.declarator(id, get_props_method(binding, state, name, initial)));
declarations.push(b.declarator(id, get_prop_source(state, name, initial)));
}
} else {
// RestElement

@ -1479,17 +1479,6 @@ export function prop_source(props, key, flags, default_value) {
return /** @type {import('./types.js').Signal<V>} */ (source_signal);
}
/**
* If the prop is readonly and has no fallback value, we can use this function, else we need to use `prop_source`.
* @param {Record<string, unknown>} props
* @param {string} key
* @returns {any}
*/
export function prop(props, key) {
// TODO skip this, and rewrite as `$$props.foo`
return () => props[key];
}
/**
* @param {boolean} immutable
* @param {unknown} a

@ -7,7 +7,6 @@ export {
source,
mutable_source,
derived,
prop,
prop_source,
user_effect,
render_effect,

Loading…
Cancel
Save