Comparing version 5.2.8 to 5.2.9
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.2.8", | ||
"version": "5.2.9", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "types": "./types/index.d.ts", |
@@ -10,3 +10,2 @@ /** @import { Visitors } from 'zimmerframe' */ | ||
* @typedef {{ | ||
* stylesheet: Compiler.Css.StyleSheet; | ||
* element: Compiler.AST.RegularElement | Compiler.AST.SvelteElement; | ||
@@ -65,5 +64,5 @@ * from_render_tag: boolean; | ||
walk(stylesheet, { stylesheet, element: parent, from_render_tag: true }, visitors); | ||
walk(stylesheet, { element: parent, from_render_tag: true }, visitors); | ||
} else { | ||
walk(stylesheet, { stylesheet, element, from_render_tag: false }, visitors); | ||
walk(stylesheet, { element, from_render_tag: false }, visitors); | ||
} | ||
@@ -887,113 +886,59 @@ } | ||
/** | ||
* Finds the given node's previous sibling in the DOM | ||
* | ||
* The Svelte `<slot>` is just a placeholder and is not actually real. Any children nodes | ||
* in `<slot>` are 'flattened' and considered as the same level as the `<slot>`'s siblings | ||
* | ||
* e.g. | ||
* ```html | ||
* <h1>Heading 1</h1> | ||
* <slot> | ||
* <h2>Heading 2</h2> | ||
* </slot> | ||
* ``` | ||
* | ||
* is considered to look like: | ||
* ```html | ||
* <h1>Heading 1</h1> | ||
* <h2>Heading 2</h2> | ||
* ``` | ||
* @param {Compiler.SvelteNode} node | ||
* @returns {Compiler.SvelteNode} | ||
* @param {Compiler.AST.RegularElement | Compiler.AST.SvelteElement} element | ||
* @param {boolean} adjacent_only | ||
* @returns {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag, NodeExistsValue>} | ||
*/ | ||
function find_previous_sibling(node) { | ||
function get_possible_element_siblings(element, adjacent_only) { | ||
/** @type {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag, NodeExistsValue>} */ | ||
const result = new Map(); | ||
const path = element.metadata.path; | ||
/** @type {Compiler.SvelteNode} */ | ||
let current_node = node; | ||
let current = element; | ||
while ( | ||
// @ts-expect-error TODO | ||
!current_node.prev && | ||
// @ts-expect-error TODO | ||
current_node.parent?.type === 'SlotElement' | ||
) { | ||
// @ts-expect-error TODO | ||
current_node = current_node.parent; | ||
} | ||
let i = path.length; | ||
// @ts-expect-error | ||
current_node = current_node.prev; | ||
while (i--) { | ||
const fragment = /** @type {Compiler.AST.Fragment} */ (path[i--]); | ||
let j = fragment.nodes.indexOf(current); | ||
while (current_node?.type === 'SlotElement') { | ||
const slot_children = current_node.fragment.nodes; | ||
if (slot_children.length > 0) { | ||
current_node = slot_children[slot_children.length - 1]; | ||
} else { | ||
break; | ||
} | ||
} | ||
while (j--) { | ||
const node = fragment.nodes[j]; | ||
return current_node; | ||
} | ||
if (node.type === 'RegularElement') { | ||
const has_slot_attribute = node.attributes.some( | ||
(attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot' | ||
); | ||
/** | ||
* @param {Compiler.SvelteNode} node | ||
* @param {boolean} adjacent_only | ||
* @returns {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag, NodeExistsValue>} | ||
*/ | ||
function get_possible_element_siblings(node, adjacent_only) { | ||
/** @type {Map<Compiler.AST.RegularElement | Compiler.AST.SvelteElement | Compiler.AST.SlotElement | Compiler.AST.RenderTag, NodeExistsValue>} */ | ||
const result = new Map(); | ||
if (!has_slot_attribute) { | ||
result.set(node, NODE_DEFINITELY_EXISTS); | ||
/** @type {Compiler.SvelteNode} */ | ||
let prev = node; | ||
while ((prev = find_previous_sibling(prev))) { | ||
if (prev.type === 'RegularElement') { | ||
if ( | ||
!prev.attributes.find( | ||
(attr) => attr.type === 'Attribute' && attr.name.toLowerCase() === 'slot' | ||
) | ||
) { | ||
result.set(prev, NODE_DEFINITELY_EXISTS); | ||
if (adjacent_only) { | ||
return result; | ||
} | ||
} | ||
} else if (is_block(node)) { | ||
if (node.type === 'SlotElement') { | ||
result.set(node, NODE_PROBABLY_EXISTS); | ||
} | ||
const possible_last_child = get_possible_last_child(node, adjacent_only); | ||
add_to_map(possible_last_child, result); | ||
if (adjacent_only && has_definite_elements(possible_last_child)) { | ||
return result; | ||
} | ||
} else if (node.type === 'RenderTag' || node.type === 'SvelteElement') { | ||
result.set(node, NODE_PROBABLY_EXISTS); | ||
// Special case: slots, render tags and svelte:element tags could resolve to no siblings, | ||
// so we want to continue until we find a definite sibling even with the adjacent-only combinator | ||
} | ||
if (adjacent_only) { | ||
break; | ||
} | ||
} else if (is_block(prev)) { | ||
const possible_last_child = get_possible_last_child(prev, adjacent_only); | ||
add_to_map(possible_last_child, result); | ||
if (adjacent_only && has_definite_elements(possible_last_child)) { | ||
return result; | ||
} | ||
} else if ( | ||
prev.type === 'SlotElement' || | ||
prev.type === 'RenderTag' || | ||
prev.type === 'SvelteElement' | ||
) { | ||
result.set(prev, NODE_PROBABLY_EXISTS); | ||
// Special case: slots, render tags and svelte:element tags could resolve to no siblings, | ||
// so we want to continue until we find a definite sibling even with the adjacent-only combinator | ||
} | ||
} | ||
if (!prev || !adjacent_only) { | ||
/** @type {Compiler.SvelteNode | null} */ | ||
let parent = node; | ||
current = path[i]; | ||
while ( | ||
// @ts-expect-error TODO | ||
(parent = parent?.parent) && | ||
is_block(parent) | ||
) { | ||
const possible_siblings = get_possible_element_siblings(parent, adjacent_only); | ||
add_to_map(possible_siblings, result); | ||
if (!current || !is_block(current)) break; | ||
// @ts-expect-error | ||
if (parent.type === 'EachBlock' && !parent.fallback?.nodes.includes(node)) { | ||
// `{#each ...}<a /><b />{/each}` — `<b>` can be previous sibling of `<a />` | ||
add_to_map(get_possible_last_child(parent, adjacent_only), result); | ||
} | ||
if (adjacent_only && has_definite_elements(possible_siblings)) { | ||
break; | ||
} | ||
if (current.type === 'EachBlock' && fragment === current.body) { | ||
// `{#each ...}<a /><b />{/each}` — `<b>` can be previous sibling of `<a />` | ||
add_to_map(get_possible_last_child(current, adjacent_only), result); | ||
} | ||
@@ -1006,3 +951,3 @@ } | ||
/** | ||
* @param {Compiler.AST.EachBlock | Compiler.AST.IfBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock} node | ||
* @param {Compiler.AST.EachBlock | Compiler.AST.IfBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock | Compiler.AST.SlotElement} node | ||
* @param {boolean} adjacent_only | ||
@@ -1031,2 +976,3 @@ * @returns {Map<Compiler.AST.RegularElement, NodeExistsValue>} | ||
case 'KeyBlock': | ||
case 'SlotElement': | ||
fragments.push(node.fragment); | ||
@@ -1039,3 +985,3 @@ break; | ||
let exhaustive = true; | ||
let exhaustive = node.type !== 'SlotElement'; | ||
@@ -1132,3 +1078,3 @@ for (const fragment of fragments) { | ||
* @param {Compiler.SvelteNode} node | ||
* @returns {node is Compiler.AST.IfBlock | Compiler.AST.EachBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock} | ||
* @returns {node is Compiler.AST.IfBlock | Compiler.AST.EachBlock | Compiler.AST.AwaitBlock | Compiler.AST.KeyBlock | Compiler.AST.SlotElement} | ||
*/ | ||
@@ -1140,4 +1086,5 @@ function is_block(node) { | ||
node.type === 'AwaitBlock' || | ||
node.type === 'KeyBlock' | ||
node.type === 'KeyBlock' || | ||
node.type === 'SlotElement' | ||
); | ||
} |
@@ -290,2 +290,3 @@ /** @import { Expression, Node, Program } from 'estree' */ | ||
const declaration = instance.scope.get(store_name); | ||
const init = /** @type {Node | undefined} */ (declaration?.initial); | ||
@@ -299,5 +300,5 @@ // If we're not in legacy mode through the compiler option, assume the user | ||
// const state = $state(0) is valid | ||
(get_rune(declaration.initial, instance.scope) === null || | ||
(get_rune(init, instance.scope) === null || | ||
// rune-line names received as props are valid too (but we have to protect against $props as store) | ||
(store_name !== 'props' && get_rune(declaration.initial, instance.scope) === '$props')) && | ||
(store_name !== 'props' && get_rune(init, instance.scope) === '$props')) && | ||
// allow `import { derived } from 'svelte/store'` in the same file as `const x = $derived(..)` because one is not a subscription to the other | ||
@@ -304,0 +305,0 @@ !( |
@@ -262,3 +262,4 @@ /** @import { ArrowFunctionExpression, Expression, FunctionDeclaration, FunctionExpression, Identifier, Pattern, PrivateIdentifier, Statement } from 'estree' */ | ||
binding.initial.type !== 'ImportDeclaration' && | ||
binding.initial.type !== 'EachBlock' | ||
binding.initial.type !== 'EachBlock' && | ||
binding.initial.type !== 'SnippetBlock' | ||
) { | ||
@@ -265,0 +266,0 @@ return should_proxy(binding.initial, null); |
@@ -78,3 +78,3 @@ /** @import { ClassDeclaration, Expression, FunctionDeclaration, Identifier, ImportDeclaration, MemberExpression, Node, Pattern, VariableDeclarator } from 'estree' */ | ||
* @param {DeclarationKind} declaration_kind | ||
* @param {null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration | AST.EachBlock} initial | ||
* @param {null | Expression | FunctionDeclaration | ClassDeclaration | ImportDeclaration | AST.EachBlock | AST.SnippetBlock} initial | ||
* @returns {Binding} | ||
@@ -636,3 +636,3 @@ */ | ||
} | ||
scope.declare(node.expression, 'normal', 'function', node.expression); | ||
scope.declare(node.expression, 'normal', 'function', node); | ||
@@ -731,3 +731,3 @@ const child_scope = state.scope.child(); | ||
* Returns the name of the rune if the given expression is a `CallExpression` using a rune. | ||
* @param {Node | AST.EachBlock | null | undefined} node | ||
* @param {Node | null | undefined} node | ||
* @param {Scope} scope | ||
@@ -734,0 +734,0 @@ */ |
@@ -294,3 +294,4 @@ import type { | ||
| ImportDeclaration | ||
| AST.EachBlock; | ||
| AST.EachBlock | ||
| AST.SnippetBlock; | ||
is_called: boolean; | ||
@@ -297,0 +298,0 @@ references: { node: Identifier; path: SvelteNode[] }[]; |
@@ -170,3 +170,3 @@ /** | ||
* @param {string} tag | ||
* @param {string | null} parent_tag | ||
* @param {string} parent_tag | ||
* @returns {boolean} | ||
@@ -177,16 +177,14 @@ */ | ||
if (parent_tag !== null) { | ||
const disallowed = disallowed_children[parent_tag]; | ||
const disallowed = disallowed_children[parent_tag]; | ||
if (disallowed) { | ||
if ('direct' in disallowed && disallowed.direct.includes(tag)) { | ||
return false; | ||
} | ||
if ('descendant' in disallowed && disallowed.descendant.includes(tag)) { | ||
return false; | ||
} | ||
if ('only' in disallowed && disallowed.only) { | ||
return disallowed.only.includes(tag); | ||
} | ||
if (disallowed) { | ||
if ('direct' in disallowed && disallowed.direct.includes(tag)) { | ||
return false; | ||
} | ||
if ('descendant' in disallowed && disallowed.descendant.includes(tag)) { | ||
return false; | ||
} | ||
if ('only' in disallowed && disallowed.only) { | ||
return disallowed.only.includes(tag); | ||
} | ||
} | ||
@@ -193,0 +191,0 @@ |
@@ -17,2 +17,3 @@ /** @import { Effect, Source, TemplateNode } from '#client' */ | ||
import { queue_micro_task } from '../task.js'; | ||
import { UNINITIALIZED } from '../../../../constants.js'; | ||
@@ -44,4 +45,4 @@ const PENDING = 0; | ||
/** @type {V | Promise<V> | null} */ | ||
var input; | ||
/** @type {V | Promise<V> | typeof UNINITIALIZED} */ | ||
var input = UNINITIALIZED; | ||
@@ -161,4 +162,4 @@ /** @type {Effect | null} */ | ||
// Set the input to null, in order to disable the promise callbacks | ||
return () => (input = null); | ||
// Set the input to something else, in order to disable the promise callbacks | ||
return () => (input = UNINITIALIZED); | ||
}); | ||
@@ -165,0 +166,0 @@ |
@@ -45,2 +45,7 @@ /** @import { Derived, Effect } from '#client' */ | ||
var parent_derived = | ||
active_reaction !== null && (active_reaction.f & DERIVED) !== 0 | ||
? /** @type {Derived} */ (active_reaction) | ||
: null; | ||
/** @type {Derived<V>} */ | ||
@@ -57,8 +62,7 @@ const signal = { | ||
version: 0, | ||
parent: active_effect | ||
parent: parent_derived ?? active_effect | ||
}; | ||
if (active_reaction !== null && (active_reaction.f & DERIVED) !== 0) { | ||
var derived = /** @type {Derived} */ (active_reaction); | ||
(derived.children ??= []).push(signal); | ||
if (parent_derived !== null) { | ||
(parent_derived.children ??= []).push(signal); | ||
} | ||
@@ -110,2 +114,17 @@ | ||
/** | ||
* @param {Derived} derived | ||
* @returns {Effect | null} | ||
*/ | ||
function get_derived_parent_effect(derived) { | ||
var parent = derived.parent; | ||
while (parent !== null) { | ||
if ((parent.f & DERIVED) === 0) { | ||
return /** @type {Effect} */ (parent); | ||
} | ||
parent = parent.parent; | ||
} | ||
return null; | ||
} | ||
/** | ||
* @template T | ||
@@ -119,3 +138,3 @@ * @param {Derived} derived | ||
set_active_effect(derived.parent); | ||
set_active_effect(get_derived_parent_effect(derived)); | ||
@@ -169,12 +188,11 @@ if (DEV) { | ||
/** | ||
* @param {Derived} signal | ||
* @param {Derived} derived | ||
* @returns {void} | ||
*/ | ||
export function destroy_derived(signal) { | ||
destroy_derived_children(signal); | ||
remove_reactions(signal, 0); | ||
set_signal_status(signal, DESTROYED); | ||
export function destroy_derived(derived) { | ||
destroy_derived_children(derived); | ||
remove_reactions(derived, 0); | ||
set_signal_status(derived, DESTROYED); | ||
// TODO we need to ensure we remove the derived from any parent derives | ||
signal.v = signal.children = signal.deps = signal.ctx = signal.reactions = null; | ||
derived.v = derived.children = derived.deps = derived.ctx = derived.reactions = null; | ||
} |
@@ -26,3 +26,2 @@ import type { ComponentContext, Dom, Equals, TemplateNode, TransitionManager } from '#client'; | ||
deps: null | Value[]; | ||
parent: Effect | null; | ||
} | ||
@@ -35,2 +34,4 @@ | ||
children: null | Reaction[]; | ||
/** Parent effect or derived */ | ||
parent: Effect | Derived | null; | ||
} | ||
@@ -63,2 +64,4 @@ | ||
last: null | Effect; | ||
/** Parent effect */ | ||
parent: Effect | null; | ||
/** Dev only */ | ||
@@ -65,0 +68,0 @@ component_function?: any; |
@@ -770,5 +770,20 @@ /** @import { ComponentContext, Derived, Effect, Reaction, Signal, Source, Value } from '#client' */ | ||
var parent = derived.parent; | ||
var target = derived; | ||
if (parent !== null && !parent.deriveds?.includes(derived)) { | ||
(parent.deriveds ??= []).push(derived); | ||
while (parent !== null) { | ||
// Attach the derived to the nearest parent effect, if there are deriveds | ||
// in between then we also need to attach them too | ||
if ((parent.f & DERIVED) !== 0) { | ||
var parent_derived = /** @type {Derived} */ (parent); | ||
target = parent_derived; | ||
parent = parent_derived.parent; | ||
} else { | ||
var parent_effect = /** @type {Effect} */ (parent); | ||
if (!parent_effect.deriveds?.includes(target)) { | ||
(parent_effect.deriveds ??= []).push(target); | ||
} | ||
break; | ||
} | ||
} | ||
@@ -775,0 +790,0 @@ } |
@@ -37,3 +37,3 @@ /** @import { Component, Payload } from '#server' */ | ||
* @param {Payload} payload | ||
* @param {Element | null} parent | ||
* @param {Element} parent | ||
* @param {Element} child | ||
@@ -43,5 +43,3 @@ */ | ||
var message = | ||
(parent === null | ||
? `node_invalid_placement_ssr: ${stringify(child)} needs a valid parent element\n\n` | ||
: `node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n`) + | ||
`node_invalid_placement_ssr: ${stringify(parent)} cannot contain ${stringify(child)}\n\n` + | ||
'This can cause content to shift around as the browser repairs the HTML, and will likely result in a `hydration_mismatch` warning.'; | ||
@@ -90,4 +88,2 @@ | ||
} | ||
} else if (!is_tag_valid_with_parent(tag, null)) { | ||
print_error(payload, null, child); | ||
} | ||
@@ -94,0 +90,0 @@ |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.2.8'; | ||
export const VERSION = '5.2.9'; | ||
export const PUBLIC_VERSION = '5'; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
2330101
51360