Merge branch 'main' into unify-pre-effects

unify-pre-effects
Rich Harris 3 months ago committed by GitHub
commit 5c365e8983
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -163,6 +163,7 @@
"loud-cheetahs-flow",
"loud-ravens-drop",
"lovely-carpets-lick",
"lovely-houses-own",
"lovely-items-turn",
"lovely-rules-eat",
"lucky-schools-hang",
@ -225,6 +226,7 @@
"real-guests-do",
"real-items-suffer",
"real-pandas-brush",
"red-cycles-pretend",
"red-doors-own",
"red-feet-worry",
"red-poets-study",
@ -297,6 +299,7 @@
"spotty-turkeys-sparkle",
"stale-books-perform",
"stale-comics-look",
"stale-fans-rest",
"stale-jeans-refuse",
"strange-apricots-happen",
"strong-gifts-smoke",

@ -1,5 +1,15 @@
# svelte
## 5.0.0-next.84
### Patch Changes
- fix: reliably remove undefined attributes during hydration ([#10917](https://github.com/sveltejs/svelte/pull/10917))
- fix: Add `elementtiming` HTMLAttribute, remove `crossorigin` from HTMLInputAttributes ([#10921](https://github.com/sveltejs/svelte/pull/10921))
- feat: shorter compiler output for attribute updates ([#10917](https://github.com/sveltejs/svelte/pull/10917))
## 5.0.0-next.83
### Patch Changes

@ -2,7 +2,7 @@
"name": "svelte",
"description": "Cybernetically enhanced web apps",
"license": "MIT",
"version": "5.0.0-next.83",
"version": "5.0.0-next.84",
"type": "module",
"types": "./types/index.d.ts",
"engines": {

@ -32,12 +32,7 @@ export interface ComponentClientTransformState extends ClientTransformState {
/** Stuff that happens before the render effect(s) */
readonly init: Statement[];
/** Stuff that happens inside the render effect */
readonly update: {
/** If the update array only contains a single entry, this singular entry will be used, if present */
singular?: Statement;
/** Used if condition for singular prop is false (see comment above) */
grouped: Statement;
}[];
readonly update: Statement[];
/** Stuff that happens after the render effect (control blocks, dynamic elements, bindings, actions, etc) */
readonly after_update: Statement[];
/** The HTML template string */

@ -59,7 +59,7 @@ function get_attribute_name(element, attribute, context) {
}
/**
* Serializes each style directive into something like `$.style(element, style_property, value)`
* Serializes each style directive into something like `$.set_style(element, style_property, value)`
* and adds it either to init or update, depending on whether or not the value or the attributes are dynamic.
* @param {import('#compiler').StyleDirective[]} style_directives
* @param {import('estree').Identifier} element_id
@ -74,9 +74,10 @@ function serialize_style_directives(style_directives, element_id, context, is_at
directive.value === true
? serialize_get_binding({ name: directive.name, type: 'Identifier' }, context.state)
: serialize_attribute_value(directive.value, context)[1];
const grouped = b.stmt(
const update = b.stmt(
b.call(
'$.style',
'$.set_style',
element_id,
b.literal(directive.name),
value,
@ -85,17 +86,6 @@ function serialize_style_directives(style_directives, element_id, context, is_at
)
)
);
const singular = b.stmt(
b.call(
'$.style_effect',
element_id,
b.literal(directive.name),
b.arrow([], value),
/** @type {import('estree').Expression} */ (
directive.modifiers.includes('important') ? b.true : undefined
)
)
);
const contains_call_expression =
Array.isArray(directive.value) &&
@ -104,11 +94,11 @@ function serialize_style_directives(style_directives, element_id, context, is_at
);
if (!is_attributes_reactive && contains_call_expression) {
state.init.push(singular);
state.init.push(serialize_update(update));
} else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) {
state.update.push({ grouped, singular });
state.update.push(update);
} else {
state.init.push(grouped);
state.init.push(update);
}
}
}
@ -146,18 +136,15 @@ function serialize_class_directives(class_directives, element_id, context, is_at
const state = context.state;
for (const directive of class_directives) {
const value = /** @type {import('estree').Expression} */ (context.visit(directive.expression));
const grouped = b.stmt(b.call('$.class_toggle', element_id, b.literal(directive.name), value));
const singular = b.stmt(
b.call('$.class_toggle_effect', element_id, b.literal(directive.name), b.arrow([], value))
);
const update = b.stmt(b.call('$.toggle_class', element_id, b.literal(directive.name), value));
const contains_call_expression = directive.expression.type === 'CallExpression';
if (!is_attributes_reactive && contains_call_expression) {
state.init.push(singular);
state.init.push(serialize_update(update));
} else if (is_attributes_reactive || directive.metadata.dynamic || contains_call_expression) {
state.update.push({ grouped, singular });
state.update.push(update);
} else {
state.init.push(grouped);
state.init.push(update);
}
}
}
@ -293,23 +280,14 @@ function serialize_element_spread_attributes(
const lowercase_attributes =
element.metadata.svg || is_custom_element_node(element) ? b.false : b.true;
const id = context.state.scope.generate('spread_attributes');
const id = context.state.scope.generate('attributes');
const standalone = b.stmt(
b.call(
'$.spread_attributes_effect',
element_id,
b.thunk(b.array(values)),
lowercase_attributes,
b.literal(context.state.analysis.css.hash)
)
);
const inside_effect = b.stmt(
const update = b.stmt(
b.assignment(
'=',
b.id(id),
b.call(
'$.spread_attributes',
'$.set_attributes',
element_id,
b.id(id),
b.array(values),
@ -319,32 +297,21 @@ function serialize_element_spread_attributes(
)
);
if (!needs_isolation || needs_select_handling) {
context.state.init.push(b.let(id));
}
context.state.init.push(b.let(id));
// objects could contain reactive getters -> play it safe and always assume spread attributes are reactive
if (needs_isolation) {
if (needs_select_handling) {
context.state.init.push(
b.stmt(b.call('$.render_effect', b.arrow([], b.block([inside_effect]))))
);
} else {
context.state.init.push(standalone);
}
context.state.init.push(serialize_update(update));
} else {
context.state.update.push({
singular: needs_select_handling ? undefined : standalone,
grouped: inside_effect
});
context.state.update.push(update);
}
if (needs_select_handling) {
context.state.init.push(
b.stmt(b.call('$.init_select', element_id, b.thunk(b.member(b.id(id), b.id('value')))))
);
context.state.update.push({
grouped: b.if(
context.state.update.push(
b.if(
b.binary('in', b.literal('value'), b.id(id)),
b.block([
// This ensures a one-way street to the DOM in case it's <select {value}>
@ -354,7 +321,7 @@ function serialize_element_spread_attributes(
b.stmt(b.call('$.select_option', element_id, b.member(b.id(id), b.id('value'))))
])
)
});
);
}
}
@ -370,12 +337,14 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
if (attributes.length === 0) {
if (context.state.analysis.css.hash) {
context.state.init.push(
b.stmt(b.call('$.class_name', element_id, b.literal(context.state.analysis.css.hash)))
b.stmt(b.call('$.set_class', element_id, b.literal(context.state.analysis.css.hash)))
);
}
return false;
}
// TODO why are we always treating this as a spread? needs docs, if that's not an error
let needs_isolation = false;
let is_reactive = false;
@ -398,52 +367,45 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
attribute.type === 'SpreadAttribute' && attribute.metadata.contains_call_expression;
}
const isolated = b.stmt(
b.call(
'$.spread_dynamic_element_attributes_effect',
element_id,
b.thunk(b.array(values)),
b.literal(context.state.analysis.css.hash)
)
);
if (needs_isolation) {
context.state.init.push(isolated);
return false;
} else if (is_reactive) {
const id = context.state.scope.generate('spread_attributes');
if (needs_isolation || is_reactive) {
const id = context.state.scope.generate('attributes');
context.state.init.push(b.let(id));
context.state.update.push({
singular: isolated,
grouped: b.stmt(
b.assignment(
'=',
b.id(id),
b.call(
'$.spread_dynamic_element_attributes',
element_id,
b.id(id),
b.array(values),
b.literal(context.state.analysis.css.hash)
)
)
)
});
return true;
} else {
context.state.init.push(
b.stmt(
const update = b.stmt(
b.assignment(
'=',
b.id(id),
b.call(
'$.spread_dynamic_element_attributes',
'$.set_dynamic_element_attributes',
element_id,
b.literal(null),
b.id(id),
b.array(values),
b.literal(context.state.analysis.css.hash)
)
)
);
return false;
if (needs_isolation) {
context.state.init.push(serialize_update(update));
return false;
}
context.state.update.push(update);
return true;
}
context.state.init.push(
b.stmt(
b.call(
'$.set_dynamic_element_attributes',
element_id,
b.literal(null),
b.array(values),
b.literal(context.state.analysis.css.hash)
)
)
);
return false;
}
/**
@ -453,7 +415,7 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
* ```js
* element.property = value;
* // or
* $.attr(element, property, value);
* $.set_attribute(element, property, value);
* });
* ```
* Resulting code for dynamic looks something like this:
@ -463,7 +425,7 @@ function serialize_dynamic_element_attributes(attributes, context, element_id) {
* if (value !== (value = 'new value')) {
* element.property = value;
* // or
* $.attr(element, property, value);
* $.set_attribute(element, property, value);
* }
* });
* ```
@ -482,7 +444,9 @@ function serialize_element_attribute_update_assignment(element, node_id, attribu
// The foreign namespace doesn't have any special handling, everything goes through the attr function
if (context.state.metadata.namespace === 'foreign') {
const statement = { grouped: b.stmt(b.call('$.attr', node_id, b.literal(name), value)) };
const statement = {
grouped: b.stmt(b.call('$.set_attribute', node_id, b.literal(name), value))
};
if (attribute.metadata.dynamic) {
const id = state.scope.generate(`${node_id.name}_${name}`);
serialize_update_assignment(state, id, undefined, value, statement, contains_call_expression);
@ -493,84 +457,32 @@ function serialize_element_attribute_update_assignment(element, node_id, attribu
}
}
let grouped_value = value;
if (name === 'autofocus') {
state.init.push(b.stmt(b.call('$.autofocus', node_id, value)));
return false;
}
/** @type {import('estree').Statement} */
let update;
if (name === 'class') {
grouped_value = b.call('$.to_class', value);
update = b.stmt(b.call(is_svg ? '$.set_svg_class' : '$.set_class', node_id, value));
} else if (DOMProperties.includes(name)) {
update = b.stmt(b.assignment('=', b.member(node_id, b.id(name)), value));
} else {
const callee = name.startsWith('xlink') ? '$.set_xlink_attribute' : '$.set_attribute';
update = b.stmt(b.call(callee, node_id, b.literal(name), value));
}
/**
* @param {import('estree').Expression} grouped
* @param {import('estree').Expression} [singular]
*/
const assign = (grouped, singular) => {
if (name === 'class') {
if (singular) {
return {
singular: b.stmt(
b.call(
is_svg ? '$.svg_class_name_effect' : '$.class_name_effect',
node_id,
b.thunk(singular)
)
),
grouped: b.stmt(b.call(is_svg ? '$.svg_class_name' : '$.class_name', node_id, singular))
};
}
return {
grouped: b.stmt(b.call(is_svg ? '$.svg_class_name' : '$.class_name', node_id, value))
};
} else if (!DOMProperties.includes(name)) {
if (singular) {
return {
singular: b.stmt(
b.call(
name.startsWith('xlink') ? '$.xlink_attr_effect' : '$.attr_effect',
node_id,
b.literal(name),
b.thunk(singular)
)
),
grouped: b.stmt(
b.call(
name.startsWith('xlink') ? '$.xlink_attr' : '$.attr',
node_id,
b.literal(name),
grouped
)
)
};
}
return {
grouped: b.stmt(
b.call(
name.startsWith('xlink') ? '$.xlink_attr' : '$.attr',
node_id,
b.literal(name),
grouped
)
)
};
} else {
return { grouped: b.stmt(b.assignment('=', b.member(node_id, b.id(name)), grouped)) };
}
};
if (attribute.metadata.dynamic) {
const { grouped, singular } = assign(grouped_value, value);
if (contains_call_expression && singular) {
state.init.push(singular);
if (contains_call_expression) {
state.init.push(serialize_update(update));
} else {
state.update.push({ singular, grouped });
state.update.push(update);
}
return true;
} else {
state.init.push(assign(grouped_value).grouped);
state.init.push(update);
return false;
}
}
@ -586,40 +498,18 @@ function serialize_custom_element_attribute_update_assignment(node_id, attribute
const state = context.state;
const name = attribute.name; // don't lowercase, as we set the element's property, which might be case sensitive
let [contains_call_expression, value] = serialize_attribute_value(attribute.value, context);
let grouped_value = value;
/**
* @param {import('estree').Expression} grouped
* @param {import('estree').Expression} [singular]
*/
const assign = (grouped, singular) => {
if (singular) {
return {
singular: b.stmt(
b.call('$.set_custom_element_data_effect', node_id, b.literal(name), b.thunk(singular))
),
grouped: b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), grouped))
};
}
return {
grouped: b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), grouped))
};
};
const update = b.stmt(b.call('$.set_custom_element_data', node_id, b.literal(name), value));
if (attribute.metadata.dynamic) {
const id = state.scope.generate(`${node_id.name}_${name}`);
// TODO should this use the if condition? what if someone mutates the value passed to the ce?
serialize_update_assignment(
state,
id,
undefined,
grouped_value,
assign(b.id(id), value),
contains_call_expression
);
if (contains_call_expression) {
state.init.push(serialize_update(update));
} else {
state.update.push(update);
}
return true;
} else {
state.init.push(assign(grouped_value).grouped);
state.init.push(update);
return false;
}
}
@ -709,28 +599,18 @@ function serialize_update_assignment(state, id, init, value, assignment, contain
} else {
if (assignment.skip_condition) {
if (assignment.singular) {
state.update.push({
singular: assignment.singular,
grouped: assignment.grouped
});
state.update.push(assignment.grouped);
} else {
state.init.push(b.var(id, init));
state.update.push({
grouped
});
state.update.push(grouped);
}
} else {
if (assignment.singular) {
state.init.push(b.var(id, init));
state.update.push({
singular: assignment.singular,
grouped
});
state.update.push(grouped);
} else {
state.init.push(b.var(id, init));
state.update.push({
grouped
});
state.update.push(grouped);
}
}
}
@ -1274,16 +1154,25 @@ function get_template_function(namespace, state) {
: '$.template';
}
/**
*
* @param {import('estree').Statement} statement
*/
function serialize_update(statement) {
const body =
statement.type === 'ExpressionStatement' ? statement.expression : b.block([statement]);
return b.stmt(b.call('$.render_effect', b.thunk(body)));
}
/**
*
* @param {import('../types.js').ComponentClientTransformState} state
*/
function serialize_render_stmt(state) {
if (state.update.length === 1 && state.update[0].singular) {
return state.update[0].singular;
}
return b.stmt(b.call('$.render_effect', b.thunk(b.block(state.update.map((n) => n.grouped)))));
return state.update.length === 1
? serialize_update(state.update[0])
: b.stmt(b.call('$.render_effect', b.thunk(b.block(state.update))));
}
/**
@ -1508,27 +1397,18 @@ function process_children(nodes, expression, is_element, { visit, state }) {
const text_id = get_node_id(b.call('$.space', expression(true)), state, 'text');
const singular = b.stmt(
const update = b.stmt(
b.call(
'$.text_effect',
'$.set_text',
text_id,
b.thunk(/** @type {import('estree').Expression} */ (visit(node.expression)))
/** @type {import('estree').Expression} */ (visit(node.expression))
)
);
if (node.metadata.contains_call_expression && !within_bound_contenteditable) {
state.init.push(singular);
state.init.push(serialize_update(update));
} else if (node.metadata.dynamic && !within_bound_contenteditable) {
state.update.push({
singular,
grouped: b.stmt(
b.call(
'$.text',
text_id,
/** @type {import('estree').Expression} */ (visit(node.expression))
)
)
});
state.update.push(update);
} else {
state.init.push(
b.stmt(
@ -1551,25 +1431,19 @@ function process_children(nodes, expression, is_element, { visit, state }) {
state.template.push(' ');
const contains_call_expression = sequence.some(
(n) => n.type === 'ExpressionTag' && n.metadata.contains_call_expression
);
const assignment = serialize_template_literal(sequence, visit, state)[1];
const init = b.stmt(b.assignment('=', b.member(text_id, b.id('nodeValue')), assignment));
const singular = b.stmt(b.call('$.text_effect', text_id, b.thunk(assignment)));
const [contains_call_expression, value] = serialize_template_literal(sequence, visit);
const update = b.stmt(b.call('$.set_text', text_id, value));
if (contains_call_expression && !within_bound_contenteditable) {
state.init.push(singular);
state.init.push(serialize_update(update));
} else if (
sequence.some((node) => node.type === 'ExpressionTag' && node.metadata.dynamic) &&
!within_bound_contenteditable
) {
state.update.push({
singular,
grouped: b.stmt(b.call('$.text', text_id, assignment))
});
state.update.push(update);
} else {
state.init.push(init);
state.init.push(b.stmt(b.assignment('=', b.member(text_id, b.id('nodeValue')), value)));
}
expression = (is_text) =>
@ -1672,22 +1546,20 @@ function serialize_attribute_value(attribute_value, context) {
}
}
return serialize_template_literal(attribute_value, context.visit, context.state);
return serialize_template_literal(attribute_value, context.visit);
}
/**
* @param {Array<import('#compiler').Text | import('#compiler').ExpressionTag>} values
* @param {(node: import('#compiler').SvelteNode) => any} visit
* @param {import('../types.js').ComponentClientTransformState} state
* @returns {[boolean, import('estree').TemplateLiteral]}
*/
function serialize_template_literal(values, visit, state) {
function serialize_template_literal(values, visit) {
/** @type {import('estree').TemplateElement[]} */
const quasis = [];
/** @type {import('estree').Expression[]} */
const expressions = [];
const scope = state.scope;
let contains_call_expression = false;
quasis.push(b.quasi(''));
@ -1711,6 +1583,7 @@ function serialize_template_literal(values, visit, state) {
}
}
// TODO instead of this tuple, return a `{ dynamic, complex, value }` object. will DRY stuff out
return [contains_call_expression, b.template(quasis, expressions)];
}
@ -3128,15 +3001,15 @@ export const template_visitors = {
)
);
} else {
state.update.push({
grouped: b.stmt(
state.update.push(
b.stmt(
b.assignment(
'=',
b.member(b.id('$.document'), b.id('title')),
serialize_template_literal(/** @type {any} */ (node.fragment.nodes), visit, state)[1]
serialize_template_literal(/** @type {any} */ (node.fragment.nodes), visit)[1]
)
)
});
);
}
},
SvelteBody(node, context) {

@ -1,6 +1,5 @@
import { DEV } from 'esm-env';
import { hydrating } from '../hydration.js';
import { render_effect } from '../../reactivity/effects.js';
import { get_descriptors, map_get, map_set, object_assign } from '../../utils.js';
import { AttributeAliases, DelegatedEvents, namespace_svg } from '../../../../constants.js';
import { delegate } from './events.js';
@ -14,28 +13,17 @@ import { autofocus } from './misc.js';
*/
export function remove_input_attr_defaults(dom) {
if (hydrating) {
attr(dom, 'value', null);
attr(dom, 'checked', null);
set_attribute(dom, 'value', null);
set_attribute(dom, 'checked', null);
}
}
/**
* @param {Element} dom
* @param {string} attribute
* @param {() => string} value
*/
export function attr_effect(dom, attribute, value) {
render_effect(() => {
attr(dom, attribute, value());
});
}
/**
* @param {Element} element
* @param {string} attribute
* @param {string | null} value
*/
export function attr(element, attribute, value) {
export function set_attribute(element, attribute, value) {
value = value == null ? null : value + '';
// @ts-expect-error
@ -64,37 +52,15 @@ export function attr(element, attribute, value) {
}
}
/**
* @param {Element} dom
* @param {string} attribute
* @param {() => string} value
*/
export function xlink_attr_effect(dom, attribute, value) {
render_effect(() => {
xlink_attr(dom, attribute, value());
});
}
/**
* @param {Element} dom
* @param {string} attribute
* @param {string} value
*/
export function xlink_attr(dom, attribute, value) {
export function set_xlink_attribute(dom, attribute, value) {
dom.setAttributeNS('http://www.w3.org/1999/xlink', attribute, value);
}
/**
* @param {any} node
* @param {string} prop
* @param {() => any} value
*/
export function set_custom_element_data_effect(node, prop, value) {
render_effect(() => {
set_custom_element_data(node, prop, value());
});
}
/**
* @param {any} node
* @param {string} prop
@ -104,26 +70,10 @@ export function set_custom_element_data(node, prop, value) {
if (prop in node) {
node[prop] = typeof node[prop] === 'boolean' && value === '' ? true : value;
} else {
attr(node, prop, value);
set_attribute(node, prop, value);
}
}
/**
* Like `spread_attributes` but self-contained
* @param {Element & ElementCSSInlineStyle} dom
* @param {() => Record<string, unknown>[]} attrs
* @param {boolean} lowercase_attributes
* @param {string} css_hash
*/
export function spread_attributes_effect(dom, attrs, lowercase_attributes, css_hash) {
/** @type {Record<string, any> | undefined} */
var current;
render_effect(() => {
current = spread_attributes(dom, current, attrs(), lowercase_attributes, css_hash);
});
}
/**
* Spreads attributes onto a DOM element, taking into account the currently set attributes
* @param {Element & ElementCSSInlineStyle} element
@ -133,7 +83,7 @@ export function spread_attributes_effect(dom, attrs, lowercase_attributes, css_h
* @param {string} css_hash
* @returns {Record<string, unknown>}
*/
export function spread_attributes(element, prev, attrs, lowercase_attributes, css_hash) {
export function set_attributes(element, prev, attrs, lowercase_attributes, css_hash) {
var next = object_assign({}, ...attrs);
var has_hash = css_hash.length !== 0;
@ -214,7 +164,7 @@ export function spread_attributes(element, prev, attrs, lowercase_attributes, cs
value += css_hash;
}
attr(element, name, value);
set_attribute(element, name, value);
}
}
}
@ -222,27 +172,13 @@ export function spread_attributes(element, prev, attrs, lowercase_attributes, cs
return next;
}
/**
* @param {Element} node
* @param {() => Record<string, unknown>[]} attrs
* @param {string} css_hash
*/
export function spread_dynamic_element_attributes_effect(node, attrs, css_hash) {
/** @type {Record<string, any> | undefined} */
var current;
render_effect(() => {
current = spread_dynamic_element_attributes(node, current, attrs(), css_hash);
});
}
/**
* @param {Element} node
* @param {Record<string, unknown> | undefined} prev
* @param {Record<string, unknown>[]} attrs
* @param {string} css_hash
*/
export function spread_dynamic_element_attributes(node, prev, attrs, css_hash) {
export function set_dynamic_element_attributes(node, prev, attrs, css_hash) {
if (node.tagName.includes('-')) {
var next = object_assign({}, ...attrs);
@ -257,15 +193,15 @@ export function spread_dynamic_element_attributes(node, prev, attrs, css_hash) {
}
return next;
} else {
return spread_attributes(
/** @type {Element & ElementCSSInlineStyle} */ (node),
prev,
attrs,
node.namespaceURI !== namespace_svg,
css_hash
);
}
return set_attributes(
/** @type {Element & ElementCSSInlineStyle} */ (node),
prev,
attrs,
node.namespaceURI !== namespace_svg,
css_hash
);
}
/**

@ -1,35 +1,12 @@
import { hydrating } from '../hydration.js';
import { set_class_name } from '../operations.js';
import { render_effect } from '../../reactivity/effects.js';
/**
* @param {HTMLElement} dom
* @param {() => string} value
* @returns {void}
*/
export function class_name_effect(dom, value) {
render_effect(() => {
class_name(dom, value());
});
}
/**
* @param {SVGElement} dom
* @param {() => string} value
* @returns {void}
*/
export function svg_class_name_effect(dom, value) {
render_effect(() => {
svg_class_name(dom, value());
});
}
/**
* @param {SVGElement} dom
* @param {string} value
* @returns {void}
*/
export function svg_class_name(dom, value) {
export function set_svg_class(dom, value) {
// @ts-expect-error need to add __className to patched prototype
var prev_class_name = dom.__className;
var next_class_name = to_class(value);
@ -58,7 +35,7 @@ export function svg_class_name(dom, value) {
* @param {string} value
* @returns {void}
*/
export function class_name(dom, value) {
export function set_class(dom, value) {
// @ts-expect-error need to add __className to patched prototype
var prev_class_name = dom.__className;
var next_class_name = to_class(value);
@ -90,7 +67,7 @@ export function class_name(dom, value) {
* @param {V} value
* @returns {string | V}
*/
export function to_class(value) {
function to_class(value) {
return value == null ? '' : value;
}
@ -100,22 +77,10 @@ export function to_class(value) {
* @param {boolean} value
* @returns {void}
*/
export function class_toggle(dom, class_name, value) {
export function toggle_class(dom, class_name, value) {
if (value) {
dom.classList.add(class_name);
} else {
dom.classList.remove(class_name);
}
}
/**
* @param {Element} dom
* @param {string} class_name
* @param {() => boolean} value
* @returns {void}
*/
export function class_toggle_effect(dom, class_name, value) {
render_effect(() => {
class_toggle(dom, class_name, value());
});
}

@ -1,12 +1,10 @@
import { render_effect } from '../../reactivity/effects.js';
/**
* @param {HTMLElement} dom
* @param {string} key
* @param {string} value
* @param {boolean} [important]
*/
export function style(dom, key, value, important) {
export function set_style(dom, key, value, important) {
const style = dom.style;
const prev_value = style.getPropertyValue(key);
if (value == null) {
@ -17,17 +15,3 @@ export function style(dom, key, value, important) {
style.setProperty(key, value, important ? 'important' : '');
}
}
/**
* @param {HTMLElement} dom
* @param {string} key
* @param {() => string} value
* @param {boolean} [important]
* @returns {void}
*/
export function style_effect(dom, key, value, important) {
render_effect(() => {
const string = value();
style(dom, key, string, important);
});
}

@ -39,21 +39,12 @@ export function set_should_intro(value) {
should_intro = value;
}
/**
* @param {Element} dom
* @param {() => string} value
* @returns {void}
*/
export function text_effect(dom, value) {
render_effect(() => text(dom, value()));
}
/**
* @param {Element} dom
* @param {string} value
* @returns {void}
*/
export function text(dom, value) {
export function set_text(dom, value) {
// @ts-expect-error need to add __value to patched prototype
const prev_node_value = dom.__nodeValue;
const next_node_value = stringify(value);

@ -6,5 +6,5 @@
* https://svelte.dev/docs/svelte-compiler#svelte-version
* @type {string}
*/
export const VERSION = '5.0.0-next.83';
export const VERSION = '5.0.0-next.84';
export const PUBLIC_VERSION = '5';

@ -15,26 +15,22 @@ export default function Main($$anchor, $$props) {
var div = $.first_child(fragment);
var svg = $.sibling($.sibling(div, true));
var custom_element = $.sibling($.sibling(svg, true));
var custom_element_fooBar;
var div_1 = $.sibling($.sibling(custom_element, true));
$.attr_effect(div_1, "foobar", y);
$.render_effect(() => $.set_attribute(div_1, "foobar", y()));
var svg_1 = $.sibling($.sibling(div_1, true));
$.attr_effect(svg_1, "viewBox", y);
$.render_effect(() => $.set_attribute(svg_1, "viewBox", y()));
var custom_element_1 = $.sibling($.sibling(svg_1, true));
$.set_custom_element_data_effect(custom_element_1, "fooBar", y);
$.render_effect(() => $.set_custom_element_data(custom_element_1, "fooBar", y()));
$.render_effect(() => {
$.attr(div, "foobar", x);
$.attr(svg, "viewBox", x);
if (custom_element_fooBar !== (custom_element_fooBar = x)) {
$.set_custom_element_data(custom_element, "fooBar", custom_element_fooBar);
}
$.set_attribute(div, "foobar", x);
$.set_attribute(svg, "viewBox", x);
$.set_custom_element_data(custom_element, "fooBar", x);
});
$.close_frag($$anchor, fragment);

@ -17,7 +17,7 @@ export default function Each_string_template($$anchor, $$props) {
($$anchor, thing, $$index) => {
var text = $.space_frag($$anchor);
$.text_effect(text, () => `${$.stringify($.unwrap(thing))}, `);
$.render_effect(() => $.set_text(text, `${$.stringify($.unwrap(thing))}, `));
return $.close($$anchor, text);
},
null

@ -23,7 +23,7 @@ export default function Function_prop_no_getter($$anchor, $$props) {
children: ($$anchor, $$slotProps) => {
var text = $.space_frag($$anchor);
$.text_effect(text, () => `clicks: ${$.stringify($.get(count))}`);
$.render_effect(() => $.set_text(text, `clicks: ${$.stringify($.get(count))}`));
return $.close($$anchor, text);
}
});

@ -12,7 +12,7 @@
},
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^3.0.1",
"express": "^4.18.2",
"express": "^4.19.2",
"nodemon": "^3.0.3",
"svelte": "workspace:*",
"vite": "^5.0.12"

@ -148,8 +148,8 @@ importers:
specifier: ^3.0.1
version: 3.0.1(svelte@packages+svelte)(vite@5.0.12)
express:
specifier: ^4.18.2
version: 4.18.2
specifier: ^4.19.2
version: 4.19.2
nodemon:
specifier: ^3.0.3
version: 3.0.3
@ -3341,8 +3341,8 @@ packages:
resolution: {integrity: sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==}
dev: true
/body-parser@1.20.1:
resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==}
/body-parser@1.20.2:
resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
dependencies:
bytes: 3.1.2
@ -3354,7 +3354,7 @@ packages:
iconv-lite: 0.4.24
on-finished: 2.4.1
qs: 6.11.0
raw-body: 2.5.1
raw-body: 2.5.2
type-is: 1.6.18
unpipe: 1.0.0
transitivePeerDependencies:
@ -3728,11 +3728,6 @@ packages:
resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==}
dev: true
/cookie@0.5.0:
resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==}
engines: {node: '>= 0.6'}
dev: true
/cookie@0.6.0:
resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
engines: {node: '>= 0.6'}
@ -4469,16 +4464,16 @@ packages:
resolution: {integrity: sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==}
dev: true
/express@4.18.2:
resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==}
/express@4.19.2:
resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==}
engines: {node: '>= 0.10.0'}
dependencies:
accepts: 1.3.8
array-flatten: 1.1.1
body-parser: 1.20.1
body-parser: 1.20.2
content-disposition: 0.5.4
content-type: 1.0.5
cookie: 0.5.0
cookie: 0.6.0
cookie-signature: 1.0.6
debug: 2.6.9
depd: 2.0.0
@ -6895,8 +6890,8 @@ packages:
engines: {node: '>= 0.6'}
dev: true
/raw-body@2.5.1:
resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==}
/raw-body@2.5.2:
resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==}
engines: {node: '>= 0.8'}
dependencies:
bytes: 3.1.2

Loading…
Cancel
Save