svelte
Advanced tools
Comparing version 5.0.0-next.178 to 5.0.0-next.179
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.0.0-next.178", | ||
"version": "5.0.0-next.179", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "types": "./types/index.d.ts", |
@@ -273,17 +273,24 @@ /** @import { Context } from 'zimmerframe' */ | ||
/** | ||
* In a case like `{#if x}<Foo />{/if}`, we don't need to wrap the child in | ||
* comments — we can just use the parent block's anchor for the component. | ||
* TODO extend this optimisation to other cases | ||
*/ | ||
const is_standalone = | ||
trimmed.length === 1 && | ||
((first.type === 'RenderTag' && !first.metadata.dynamic) || | ||
(first.type === 'Component' && | ||
!state.options.hmr && | ||
!first.attributes.some( | ||
(attribute) => attribute.type === 'Attribute' && attribute.name.startsWith('--') | ||
))); | ||
return { hoisted, trimmed, is_standalone }; | ||
return { | ||
hoisted, | ||
trimmed, | ||
/** | ||
* In a case like `{#if x}<Foo />{/if}`, we don't need to wrap the child in | ||
* comments — we can just use the parent block's anchor for the component. | ||
* TODO extend this optimisation to other cases | ||
*/ | ||
is_standalone: | ||
trimmed.length === 1 && | ||
((first.type === 'RenderTag' && !first.metadata.dynamic) || | ||
(first.type === 'Component' && | ||
!state.options.hmr && | ||
!first.attributes.some( | ||
(attribute) => attribute.type === 'Attribute' && attribute.name.startsWith('--') | ||
))), | ||
/** if a component or snippet starts with text, we need to add an anchor comment so that its text node doesn't get fused with its surroundings */ | ||
is_text_first: | ||
(parent.type === 'Fragment' || parent.type === 'SnippetBlock') && | ||
first && | ||
(first?.type === 'Text' || first?.type === 'ExpressionTag') | ||
}; | ||
} | ||
@@ -290,0 +297,0 @@ |
@@ -23,5 +23,5 @@ export const EACH_ITEM_REACTIVE = 1; | ||
export const HYDRATION_START = '['; | ||
/** used to indicate that an `{:else}...` block was rendered */ | ||
export const HYDRATION_START_ELSE = '[!'; | ||
export const HYDRATION_END = ']'; | ||
export const HYDRATION_ANCHOR = ''; | ||
export const HYDRATION_END_ELSE = `${HYDRATION_END}!`; // used to indicate that an `{:else}...` block was rendered | ||
export const HYDRATION_ERROR = {}; | ||
@@ -28,0 +28,0 @@ |
/** @import { SourceLocation } from '#shared' */ | ||
import { HYDRATION_END, HYDRATION_START } from '../../../constants.js'; | ||
import { HYDRATION_END, HYDRATION_START, HYDRATION_START_ELSE } from '../../../constants.js'; | ||
import { hydrating } from '../dom/hydration.js'; | ||
@@ -50,3 +50,3 @@ | ||
var comment = /** @type {Comment} */ (node); | ||
if (comment.data === HYDRATION_START) depth += 1; | ||
if (comment.data === HYDRATION_START || comment.data === HYDRATION_START_ELSE) depth += 1; | ||
else if (comment.data[0] === HYDRATION_END) depth -= 1; | ||
@@ -53,0 +53,0 @@ } |
@@ -15,3 +15,3 @@ /** @import { Effect, Source, TemplateNode } from '#client' */ | ||
import { queue_micro_task } from '../task.js'; | ||
import { hydrating } from '../hydration.js'; | ||
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js'; | ||
import { mutable_source, set, source } from '../../reactivity/sources.js'; | ||
@@ -25,3 +25,3 @@ | ||
* @template V | ||
* @param {TemplateNode} anchor | ||
* @param {TemplateNode} node | ||
* @param {(() => Promise<V>)} get_input | ||
@@ -33,3 +33,8 @@ * @param {null | ((anchor: Node) => void)} pending_fn | ||
*/ | ||
export function await_block(anchor, get_input, pending_fn, then_fn, catch_fn) { | ||
export function await_block(node, get_input, pending_fn, then_fn, catch_fn) { | ||
if (hydrating) { | ||
hydrate_next(); | ||
} | ||
var anchor = node; | ||
var runes = is_runes(); | ||
@@ -153,2 +158,6 @@ var component_context = current_component_context; | ||
}); | ||
if (hydrating) { | ||
anchor = hydrate_node; | ||
} | ||
} |
/** @import { TemplateNode } from '#client' */ | ||
import { hydrating, set_hydrate_nodes } from '../hydration.js'; | ||
import { render_effect, teardown } from '../../reactivity/effects.js'; | ||
import { hydrate_node, hydrating, set_hydrate_node } from '../hydration.js'; | ||
@@ -12,3 +12,3 @@ /** | ||
if (hydrating) { | ||
set_hydrate_nodes(/** @type {TemplateNode[]} */ ([...element.childNodes]).slice(0, -1)); | ||
set_hydrate_node(/** @type {TemplateNode} */ (element.firstChild)); | ||
} | ||
@@ -15,0 +15,0 @@ |
@@ -0,1 +1,2 @@ | ||
/** @import { TemplateNode } from '#client' */ | ||
import { | ||
@@ -8,14 +9,14 @@ EACH_INDEX_REACTIVE, | ||
EACH_KEYED, | ||
HYDRATION_END_ELSE, | ||
HYDRATION_START | ||
HYDRATION_END, | ||
HYDRATION_START_ELSE | ||
} from '../../../../constants.js'; | ||
import { | ||
hydrate_anchor, | ||
hydrate_nodes, | ||
hydrate_start, | ||
hydrate_next, | ||
hydrate_node, | ||
hydrating, | ||
remove_nodes, | ||
set_hydrate_node, | ||
set_hydrating | ||
} from '../hydration.js'; | ||
import { clear_text_content, empty } from '../operations.js'; | ||
import { remove } from '../reconciler.js'; | ||
import { | ||
@@ -100,3 +101,3 @@ block, | ||
* @template V | ||
* @param {Element | Comment} anchor The next sibling node, or the parent node if this is a 'controlled' block | ||
* @param {Element | Comment} node The next sibling node, or the parent node if this is a 'controlled' block | ||
* @param {number} flags | ||
@@ -109,3 +110,5 @@ * @param {() => V[]} get_collection | ||
*/ | ||
export function each(anchor, flags, get_collection, get_key, render_fn, fallback_fn = null) { | ||
export function each(node, flags, get_collection, get_key, render_fn, fallback_fn = null) { | ||
var anchor = node; | ||
/** @type {import('#client').EachState} */ | ||
@@ -117,11 +120,13 @@ var state = { flags, items: new Map(), first: null }; | ||
if (is_controlled) { | ||
var parent_node = /** @type {Element} */ (anchor); | ||
var parent_node = /** @type {Element} */ (node); | ||
anchor = hydrating | ||
? /** @type {Comment | Text} */ ( | ||
hydrate_anchor(/** @type {Comment | Text} */ (parent_node.firstChild)) | ||
) | ||
? set_hydrate_node(/** @type {Comment | Text} */ (parent_node.firstChild)) | ||
: parent_node.appendChild(empty()); | ||
} | ||
if (hydrating) { | ||
hydrate_next(); | ||
} | ||
/** @type {import('#client').Effect | null} */ | ||
@@ -162,7 +167,9 @@ var fallback = null; | ||
if (hydrating) { | ||
var is_else = /** @type {Comment} */ (anchor).data === HYDRATION_END_ELSE; | ||
var is_else = /** @type {Comment} */ (anchor).data === HYDRATION_START_ELSE; | ||
if (is_else !== (length === 0) || hydrate_start === undefined) { | ||
if (is_else !== (length === 0)) { | ||
// hydration mismatch — remove the server-rendered DOM and start over | ||
remove(hydrate_nodes); | ||
anchor = remove_nodes(); | ||
set_hydrate_node(anchor); | ||
set_hydrating(false); | ||
@@ -175,5 +182,2 @@ mismatch = true; | ||
if (hydrating) { | ||
/** @type {Node} */ | ||
var child_anchor = hydrate_start; | ||
/** @type {import('#client').EachItem | null} */ | ||
@@ -187,7 +191,8 @@ var prev = null; | ||
if ( | ||
child_anchor.nodeType !== 8 || | ||
/** @type {Comment} */ (child_anchor).data !== HYDRATION_START | ||
hydrate_node.nodeType === 8 && | ||
/** @type {Comment} */ (hydrate_node).data === HYDRATION_END | ||
) { | ||
// If `nodes` is null, then that means that the server rendered fewer items than what | ||
// expected, so break out and continue appending non-hydrated items | ||
// The server rendered fewer items than expected, | ||
// so break out and continue appending non-hydrated items | ||
anchor = /** @type {Comment} */ (hydrate_node); | ||
mismatch = true; | ||
@@ -198,8 +203,6 @@ set_hydrating(false); | ||
child_anchor = hydrate_anchor(child_anchor); | ||
var value = array[i]; | ||
var key = get_key(value, i); | ||
item = create_item(child_anchor, state, prev, null, value, key, i, render_fn, flags); | ||
item = create_item(hydrate_node, state, prev, null, value, key, i, render_fn, flags); | ||
state.items.set(key, item); | ||
child_anchor = /** @type {Comment} */ (child_anchor.nextSibling); | ||
@@ -211,7 +214,3 @@ prev = item; | ||
if (length > 0) { | ||
while (child_anchor !== anchor) { | ||
var next = /** @type {import('#client').TemplateNode} */ (child_anchor.nextSibling); | ||
/** @type {import('#client').TemplateNode} */ (child_anchor).remove(); | ||
child_anchor = next; | ||
} | ||
set_hydrate_node(remove_nodes()); | ||
} | ||
@@ -243,2 +242,6 @@ } | ||
}); | ||
if (hydrating) { | ||
anchor = hydrate_node; | ||
} | ||
} | ||
@@ -245,0 +248,0 @@ |
/** @import { Effect, TemplateNode } from '#client' */ | ||
import { HYDRATION_ERROR } from '../../../../constants.js'; | ||
import { block, branch, destroy_effect } from '../../reactivity/effects.js'; | ||
import { get_start, hydrate_nodes, hydrating } from '../hydration.js'; | ||
import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from '../hydration.js'; | ||
import { create_fragment_from_html } from '../reconciler.js'; | ||
import { assign_nodes } from '../template.js'; | ||
import * as w from '../../warnings.js'; | ||
/** | ||
* @param {Element | Text | Comment} anchor | ||
* @param {Element | Text | Comment} node | ||
* @param {() => string} get_value | ||
@@ -14,3 +16,5 @@ * @param {boolean} svg | ||
*/ | ||
export function html(anchor, get_value, svg, mathml) { | ||
export function html(node, get_value, svg, mathml) { | ||
var anchor = node; | ||
var value = ''; | ||
@@ -33,3 +37,20 @@ | ||
if (hydrating) { | ||
assign_nodes(get_start(), hydrate_nodes[hydrate_nodes.length - 1]); | ||
var next = hydrate_next(); | ||
var last = next; | ||
while ( | ||
next !== null && | ||
(next.nodeType !== 8 || /** @type {Comment} */ (next).data !== '') | ||
) { | ||
last = next; | ||
next = /** @type {TemplateNode} */ (next.nextSibling); | ||
} | ||
if (next === null) { | ||
w.hydration_mismatch(); | ||
throw HYDRATION_ERROR; | ||
} | ||
assign_nodes(hydrate_node, last); | ||
anchor = set_hydrate_node(next); | ||
return; | ||
@@ -36,0 +57,0 @@ } |
@@ -0,9 +1,16 @@ | ||
/** @import { TemplateNode } from '#client' */ | ||
import { EFFECT_TRANSPARENT } from '../../constants.js'; | ||
import { hydrate_nodes, hydrating, set_hydrating } from '../hydration.js'; | ||
import { remove } from '../reconciler.js'; | ||
import { | ||
hydrate_next, | ||
hydrate_node, | ||
hydrating, | ||
remove_nodes, | ||
set_hydrate_node, | ||
set_hydrating | ||
} from '../hydration.js'; | ||
import { block, branch, pause_effect, resume_effect } from '../../reactivity/effects.js'; | ||
import { HYDRATION_END_ELSE } from '../../../../constants.js'; | ||
import { HYDRATION_START_ELSE } from '../../../../constants.js'; | ||
/** | ||
* @param {Comment} anchor | ||
* @param {TemplateNode} node | ||
* @param {() => boolean} get_condition | ||
@@ -15,9 +22,9 @@ * @param {(anchor: Node) => import('#client').Dom} consequent_fn | ||
*/ | ||
export function if_block( | ||
anchor, | ||
get_condition, | ||
consequent_fn, | ||
alternate_fn = null, | ||
elseif = false | ||
) { | ||
export function if_block(node, get_condition, consequent_fn, alternate_fn = null, elseif = false) { | ||
if (hydrating) { | ||
hydrate_next(); | ||
} | ||
var anchor = node; | ||
/** @type {import('#client').Effect | null} */ | ||
@@ -41,3 +48,3 @@ var consequent_effect = null; | ||
if (hydrating) { | ||
const is_else = anchor.data === HYDRATION_END_ELSE; | ||
const is_else = /** @type {Comment} */ (anchor).data === HYDRATION_START_ELSE; | ||
@@ -47,3 +54,5 @@ if (condition === is_else) { | ||
// This could happen with `{#if browser}...{/if}`, for example | ||
remove(hydrate_nodes); | ||
anchor = remove_nodes(); | ||
set_hydrate_node(anchor); | ||
set_hydrating(false); | ||
@@ -85,2 +94,6 @@ mismatch = true; | ||
}, flags); | ||
if (hydrating) { | ||
anchor = hydrate_node; | ||
} | ||
} |
@@ -1,19 +0,26 @@ | ||
/** @import { Dom, Effect } from '#client' */ | ||
/** @import { Effect, TemplateNode } from '#client' */ | ||
import { UNINITIALIZED } from '../../../../constants.js'; | ||
import { block, branch, pause_effect } from '../../reactivity/effects.js'; | ||
import { safe_not_equal } from '../../reactivity/equality.js'; | ||
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js'; | ||
/** | ||
* @template V | ||
* @param {Comment} anchor | ||
* @param {TemplateNode} node | ||
* @param {() => V} get_key | ||
* @param {(anchor: Node) => Dom | void} render_fn | ||
* @param {(anchor: Node) => TemplateNode | void} render_fn | ||
* @returns {void} | ||
*/ | ||
export function key_block(anchor, get_key, render_fn) { | ||
export function key_block(node, get_key, render_fn) { | ||
if (hydrating) { | ||
hydrate_next(); | ||
} | ||
var anchor = node; | ||
/** @type {V | typeof UNINITIALIZED} */ | ||
let key = UNINITIALIZED; | ||
var key = UNINITIALIZED; | ||
/** @type {Effect} */ | ||
let effect; | ||
var effect; | ||
@@ -29,2 +36,6 @@ block(() => { | ||
}); | ||
if (hydrating) { | ||
anchor = hydrate_node; | ||
} | ||
} |
@@ -9,6 +9,7 @@ /** @import { Effect, TemplateNode } from '#client' */ | ||
} from '../../runtime.js'; | ||
import { hydrate_node, hydrating } from '../hydration.js'; | ||
/** | ||
* @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn | ||
* @param {TemplateNode} anchor | ||
* @param {TemplateNode} node | ||
* @param {() => SnippetFn | null | undefined} get_snippet | ||
@@ -18,3 +19,5 @@ * @param {(() => any)[]} args | ||
*/ | ||
export function snippet(anchor, get_snippet, ...args) { | ||
export function snippet(node, get_snippet, ...args) { | ||
var anchor = node; | ||
/** @type {SnippetFn | null | undefined} */ | ||
@@ -38,2 +41,6 @@ var snippet; | ||
}, EFFECT_TRANSPARENT); | ||
if (hydrating) { | ||
anchor = hydrate_node; | ||
} | ||
} | ||
@@ -40,0 +47,0 @@ |
/** @import { TemplateNode, Dom, Effect } from '#client' */ | ||
import { block, branch, pause_effect } from '../../reactivity/effects.js'; | ||
import { hydrate_next, hydrate_node, hydrating } from '../hydration.js'; | ||
@@ -7,3 +8,3 @@ /** | ||
* @template {(props: P) => void} C | ||
* @param {TemplateNode} anchor | ||
* @param {TemplateNode} node | ||
* @param {() => C} get_component | ||
@@ -13,8 +14,14 @@ * @param {(anchor: TemplateNode, component: C) => Dom | void} render_fn | ||
*/ | ||
export function component(anchor, get_component, render_fn) { | ||
export function component(node, get_component, render_fn) { | ||
if (hydrating) { | ||
hydrate_next(); | ||
} | ||
var anchor = node; | ||
/** @type {C} */ | ||
let component; | ||
var component; | ||
/** @type {Effect | null} */ | ||
let effect; | ||
var effect; | ||
@@ -33,2 +40,6 @@ block(() => { | ||
}); | ||
if (hydrating) { | ||
anchor = hydrate_node; | ||
} | ||
} |
@@ -0,3 +1,10 @@ | ||
/** @import { Effect, EffectNodes, TemplateNode } from '#client' */ | ||
import { namespace_svg } from '../../../../constants.js'; | ||
import { hydrating, set_hydrate_nodes } from '../hydration.js'; | ||
import { | ||
hydrate_next, | ||
hydrate_node, | ||
hydrating, | ||
set_hydrate_node, | ||
set_hydrating | ||
} from '../hydration.js'; | ||
import { empty } from '../operations.js'; | ||
@@ -15,5 +22,4 @@ import { | ||
import { DEV } from 'esm-env'; | ||
import { EFFECT_TRANSPARENT } from '../../constants.js'; | ||
import { assign_nodes } from '../template.js'; | ||
import { noop } from '../../../shared/utils.js'; | ||
import { EFFECT_TRANSPARENT } from '../../constants.js'; | ||
@@ -30,18 +36,29 @@ /** | ||
export function element(node, get_tag, is_svg, render_fn, get_namespace, location) { | ||
const filename = DEV && location && current_component_context?.function.filename; | ||
let was_hydrating = hydrating; | ||
if (hydrating) { | ||
hydrate_next(); | ||
} | ||
var filename = DEV && location && current_component_context?.function.filename; | ||
/** @type {string | null} */ | ||
let tag; | ||
var tag; | ||
/** @type {string | null} */ | ||
let current_tag; | ||
var current_tag; | ||
/** @type {null | Element} */ | ||
let element = hydrating && node.nodeType === 1 ? /** @type {Element} */ (node) : null; | ||
var element = null; | ||
let anchor = /** @type {Comment} */ (hydrating && element ? element.nextSibling : node); | ||
if (hydrating && hydrate_node.nodeType === 1) { | ||
element = /** @type {Element} */ (hydrate_node); | ||
hydrate_next(); | ||
} | ||
/** @type {import('#client').Effect | null} */ | ||
let effect; | ||
var anchor = /** @type {TemplateNode} */ (hydrating ? hydrate_node : node); | ||
/** @type {Effect | null} */ | ||
var effect; | ||
/** | ||
@@ -52,11 +69,7 @@ * The keyed `{#each ...}` item block, if any, that this element is inside. | ||
*/ | ||
let each_item_block = current_each_item; | ||
var each_item_block = current_each_item; | ||
block(() => { | ||
const next_tag = get_tag() || null; | ||
const ns = get_namespace | ||
? get_namespace() | ||
: is_svg || next_tag === 'svg' | ||
? namespace_svg | ||
: null; | ||
var ns = get_namespace ? get_namespace() : is_svg || next_tag === 'svg' ? namespace_svg : null; | ||
@@ -95,4 +108,2 @@ // Assumption: Noone changes the namespace but not the tag (what would that even mean?) | ||
assign_nodes(element, element); | ||
if (DEV && location) { | ||
@@ -109,11 +120,17 @@ // @ts-expect-error | ||
assign_nodes(element, element); | ||
if (render_fn) { | ||
// If hydrating, use the existing ssr comment as the anchor so that the | ||
// inner open and close methods can pick up the existing nodes correctly | ||
var child_anchor = hydrating ? element.lastChild : element.appendChild(empty()); | ||
var child_anchor = /** @type {TemplateNode} */ ( | ||
hydrating ? element.firstChild : element.appendChild(empty()) | ||
); | ||
if (hydrating && child_anchor) { | ||
set_hydrate_nodes( | ||
/** @type {import('#client').TemplateNode[]} */ ([...element.childNodes]).slice(0, -1) | ||
); | ||
if (hydrating) { | ||
if (child_anchor === null) { | ||
set_hydrating(false); | ||
} else { | ||
set_hydrate_node(child_anchor); | ||
} | ||
} | ||
@@ -128,6 +145,6 @@ | ||
// we do this after calling `render_fn` so that child effects don't override `nodes.end` | ||
/** @type {Effect & { nodes: EffectNodes }} */ (current_effect).nodes.end = element; | ||
anchor.before(element); | ||
// See below | ||
return noop; | ||
}); | ||
@@ -141,7 +158,8 @@ } | ||
set_current_each_item(previous_each_item); | ||
}, EFFECT_TRANSPARENT); | ||
// Inert effects are proactively detached from the effect tree. Returning a noop | ||
// teardown function is an easy way to ensure that this is not discarded | ||
return noop; | ||
}, EFFECT_TRANSPARENT); | ||
if (was_hydrating) { | ||
set_hydrating(true); | ||
set_hydrate_node(anchor); | ||
} | ||
} |
@@ -1,6 +0,7 @@ | ||
import { hydrate_anchor, hydrate_nodes, hydrating, set_hydrate_nodes } from '../hydration.js'; | ||
/** @import { TemplateNode } from '#client' */ | ||
import { hydrate_node, hydrating, set_hydrate_node } from '../hydration.js'; | ||
import { empty } from '../operations.js'; | ||
import { block } from '../../reactivity/effects.js'; | ||
import { HYDRATION_END, HYDRATION_START } from '../../../../constants.js'; | ||
import { HEAD_EFFECT } from '../../constants.js'; | ||
import { HYDRATION_START } from '../../../../constants.js'; | ||
@@ -17,3 +18,3 @@ /** | ||
/** | ||
* @param {(anchor: Node) => import('#client').Dom | void} render_fn | ||
* @param {(anchor: Node) => void} render_fn | ||
* @returns {void} | ||
@@ -24,3 +25,3 @@ */ | ||
// therefore we need to skip that when we detect that we're not in hydration mode. | ||
let previous_hydrate_nodes = null; | ||
let previous_hydrate_node = null; | ||
let was_hydrating = hydrating; | ||
@@ -32,7 +33,7 @@ | ||
if (hydrating) { | ||
previous_hydrate_nodes = hydrate_nodes; | ||
previous_hydrate_node = hydrate_node; | ||
// There might be multiple head blocks in our app, so we need to account for each one needing independent hydration. | ||
if (head_anchor === undefined) { | ||
head_anchor = /** @type {import('#client').TemplateNode} */ (document.head.firstChild); | ||
head_anchor = /** @type {TemplateNode} */ (document.head.firstChild); | ||
} | ||
@@ -44,7 +45,6 @@ | ||
) { | ||
head_anchor = /** @type {import('#client').TemplateNode} */ (head_anchor.nextSibling); | ||
head_anchor = /** @type {TemplateNode} */ (head_anchor.nextSibling); | ||
} | ||
head_anchor = /** @type {import('#client').TemplateNode} */ (hydrate_anchor(head_anchor)); | ||
head_anchor = /** @type {import('#client').TemplateNode} */ (head_anchor.nextSibling); | ||
head_anchor = set_hydrate_node(/** @type {TemplateNode} */ (head_anchor.nextSibling)); | ||
} else { | ||
@@ -58,5 +58,5 @@ anchor = document.head.appendChild(empty()); | ||
if (was_hydrating) { | ||
set_hydrate_nodes(/** @type {import('#client').TemplateNode[]} */ (previous_hydrate_nodes)); | ||
set_hydrate_node(/** @type {TemplateNode} */ (previous_hydrate_node)); | ||
} | ||
} | ||
} |
@@ -1,5 +0,5 @@ | ||
import { DEV } from 'esm-env'; | ||
import { HYDRATION_END, HYDRATION_START, HYDRATION_ERROR } from '../../../constants.js'; | ||
import * as w from '../warnings.js'; | ||
/** @import { TemplateNode } from '#client' */ | ||
import { HYDRATION_END, HYDRATION_START, HYDRATION_START_ELSE } from '../../../constants.js'; | ||
/** | ||
@@ -17,84 +17,55 @@ * Use this variable to guard everything related to hydration code so it can be treeshaken out | ||
/** | ||
* Array of nodes to traverse for hydration. This will be null if we're not hydrating, but for | ||
* the sake of simplicity we're not going to use `null` checks everywhere and instead rely on | ||
* the `hydrating` flag to tell whether or not we're in hydration mode at which point this is set. | ||
* @type {import('#client').TemplateNode[]} | ||
* The node that is currently being hydrated. This starts out as the first node inside the opening | ||
* <!--[--> comment, and updates each time a component calls `$.child(...)` or `$.sibling(...)`. | ||
* When entering a block (e.g. `{#if ...}`), `hydrate_node` is the block opening comment; by the | ||
* time we leave the block it is the closing comment, which serves as the block's anchor. | ||
* @type {TemplateNode} | ||
*/ | ||
export let hydrate_nodes = /** @type {any} */ (null); | ||
export let hydrate_node; | ||
/** @type {import('#client').TemplateNode} */ | ||
export let hydrate_start; | ||
/** @param {import('#client').TemplateNode[]} nodes */ | ||
export function set_hydrate_nodes(nodes) { | ||
hydrate_nodes = nodes; | ||
hydrate_start = nodes && nodes[0]; | ||
/** @param {TemplateNode} node */ | ||
export function set_hydrate_node(node) { | ||
return (hydrate_node = node); | ||
} | ||
/** | ||
* When assigning nodes to an effect during hydration, we typically want the hydration boundary comment node | ||
* immediately before `hydrate_start`. In some cases, this comment doesn't exist because we optimized it away. | ||
* TODO it might be worth storing this value separately rather than retrieving it with `previousSibling` | ||
*/ | ||
export function get_start() { | ||
return /** @type {import('#client').TemplateNode} */ ( | ||
hydrate_start.previousSibling ?? hydrate_start | ||
); | ||
export function hydrate_next() { | ||
return (hydrate_node = /** @type {TemplateNode} */ (hydrate_node.nextSibling)); | ||
} | ||
/** | ||
* This function is only called when `hydrating` is true. If passed a `<!--[-->` opening | ||
* hydration marker, it finds the corresponding closing marker and sets `hydrate_nodes` | ||
* to everything between the markers, before returning the closing marker. | ||
* @param {Node} node | ||
* @returns {Node} | ||
*/ | ||
export function hydrate_anchor(node) { | ||
if (node.nodeType !== 8) { | ||
return node; | ||
/** @param {TemplateNode} node */ | ||
export function reset(node) { | ||
if (hydrating) { | ||
hydrate_node = node; | ||
} | ||
} | ||
var current = /** @type {Node | null} */ (node); | ||
// TODO this could have false positives, if a user comment consisted of `[`. need to tighten that up | ||
if (/** @type {Comment} */ (current).data !== HYDRATION_START) { | ||
return node; | ||
export function next() { | ||
if (hydrating) { | ||
hydrate_next(); | ||
} | ||
} | ||
/** @type {Node[]} */ | ||
var nodes = []; | ||
/** | ||
* Removes all nodes starting at `hydrate_node` up until the next hydration end comment | ||
*/ | ||
export function remove_nodes() { | ||
var depth = 0; | ||
var node = hydrate_node; | ||
while ((current = /** @type {Node} */ (current).nextSibling) !== null) { | ||
if (current.nodeType === 8) { | ||
var data = /** @type {Comment} */ (current).data; | ||
while (true) { | ||
if (node.nodeType === 8) { | ||
var data = /** @type {Comment} */ (node).data; | ||
if (data === HYDRATION_START) { | ||
if (data === HYDRATION_END) { | ||
if (depth === 0) return node; | ||
depth -= 1; | ||
} else if (data === HYDRATION_START || data === HYDRATION_START_ELSE) { | ||
depth += 1; | ||
} else if (data[0] === HYDRATION_END) { | ||
if (depth === 0) { | ||
hydrate_nodes = /** @type {import('#client').TemplateNode[]} */ (nodes); | ||
hydrate_start = /** @type {import('#client').TemplateNode} */ (nodes[0]); | ||
return current; | ||
} | ||
depth -= 1; | ||
} | ||
} | ||
nodes.push(current); | ||
var next = /** @type {TemplateNode} */ (node.nextSibling); | ||
node.remove(); | ||
node = next; | ||
} | ||
let location; | ||
if (DEV) { | ||
// @ts-expect-error | ||
const loc = node.parentNode?.__svelte_meta?.loc; | ||
if (loc) { | ||
location = `${loc.file}:${loc.line}:${loc.column}`; | ||
} | ||
} | ||
w.hydration_mismatch(location); | ||
throw HYDRATION_ERROR; | ||
} |
@@ -1,6 +0,6 @@ | ||
import { hydrate_anchor, hydrate_start, hydrating } from './hydration.js'; | ||
/** @import { Effect, TemplateNode } from '#client' */ | ||
import { hydrate_node, hydrating, set_hydrate_node } from './hydration.js'; | ||
import { DEV } from 'esm-env'; | ||
import { init_array_prototype_warnings } from '../dev/equality.js'; | ||
import { current_effect } from '../runtime.js'; | ||
import { HYDRATION_ANCHOR } from '../../../constants.js'; | ||
@@ -61,15 +61,19 @@ // export these for reference in the compiled code, making global name deduplication unnecessary | ||
export function child(node) { | ||
const child = node.firstChild; | ||
if (!hydrating) return child; | ||
if (!hydrating) { | ||
return node.firstChild; | ||
} | ||
var child = /** @type {TemplateNode} */ (hydrate_node.firstChild); | ||
// Child can be null if we have an element with a single child, like `<p>{text}</p>`, where `text` is empty | ||
if (child === null) { | ||
return node.appendChild(empty()); | ||
child = hydrate_node.appendChild(empty()); | ||
} | ||
return hydrate_anchor(child); | ||
set_hydrate_node(child); | ||
return child; | ||
} | ||
/** | ||
* @param {DocumentFragment | import('#client').TemplateNode[]} fragment | ||
* @param {DocumentFragment | TemplateNode[]} fragment | ||
* @param {boolean} is_text | ||
@@ -92,15 +96,11 @@ * @returns {Node | null} | ||
// text node to hydrate — we must therefore create one | ||
if (is_text && hydrate_start?.nodeType !== 3) { | ||
if (is_text && hydrate_node?.nodeType !== 3) { | ||
var text = empty(); | ||
var effect = /** @type {import('#client').Effect} */ (current_effect); | ||
if (effect.nodes?.start === hydrate_start) { | ||
effect.nodes.start = text; | ||
} | ||
hydrate_start?.before(text); | ||
hydrate_node?.before(text); | ||
set_hydrate_node(text); | ||
return text; | ||
} | ||
return hydrate_anchor(hydrate_start); | ||
return hydrate_node; | ||
} | ||
@@ -116,14 +116,10 @@ | ||
export function sibling(node, is_text = false) { | ||
var next_sibling = /** @type {import('#client').TemplateNode} */ (node.nextSibling); | ||
if (!hydrating) { | ||
return next_sibling; | ||
return /** @type {TemplateNode} */ (node.nextSibling); | ||
} | ||
var next_sibling = /** @type {TemplateNode} */ (hydrate_node.nextSibling); | ||
var type = next_sibling.nodeType; | ||
if (type === 8 && /** @type {Comment} */ (next_sibling).data === HYDRATION_ANCHOR) { | ||
return sibling(next_sibling, is_text); | ||
} | ||
// if a sibling {expression} is empty during SSR, there might be no | ||
@@ -134,6 +130,8 @@ // text node to hydrate — we must therefore create one | ||
next_sibling?.before(text); | ||
set_hydrate_node(text); | ||
return text; | ||
} | ||
return hydrate_anchor(/** @type {Node} */ (next_sibling)); | ||
set_hydrate_node(next_sibling); | ||
return /** @type {TemplateNode} */ (next_sibling); | ||
} | ||
@@ -140,0 +138,0 @@ |
@@ -1,3 +0,1 @@ | ||
import { is_array } from '../utils.js'; | ||
/** @param {string} html */ | ||
@@ -9,17 +7,1 @@ export function create_fragment_from_html(html) { | ||
} | ||
/** | ||
* @param {import('#client').Dom} current | ||
*/ | ||
export function remove(current) { | ||
if (is_array(current)) { | ||
for (var i = 0; i < current.length; i++) { | ||
var node = current[i]; | ||
if (node.isConnected) { | ||
node.remove(); | ||
} | ||
} | ||
} else if (current.isConnected) { | ||
current.remove(); | ||
} | ||
} |
@@ -1,2 +0,3 @@ | ||
import { get_start, hydrate_nodes, hydrate_start, hydrating } from './hydration.js'; | ||
/** @import { Effect, EffectNodes, TemplateNode } from '#client' */ | ||
import { hydrate_next, hydrate_node, hydrating, set_hydrate_node } from './hydration.js'; | ||
import { empty } from './operations.js'; | ||
@@ -9,7 +10,7 @@ import { create_fragment_from_html } from './reconciler.js'; | ||
/** | ||
* @param {import('#client').TemplateNode} start | ||
* @param {import('#client').TemplateNode} end | ||
* @param {TemplateNode} start | ||
* @param {TemplateNode | null} end | ||
*/ | ||
export function assign_nodes(start, end) { | ||
/** @type {import('#client').Effect} */ (current_effect).nodes ??= { start, end }; | ||
/** @type {Effect} */ (current_effect).nodes ??= { start, end }; | ||
} | ||
@@ -38,5 +39,4 @@ | ||
if (hydrating) { | ||
assign_nodes(get_start(), hydrate_nodes[hydrate_nodes.length - 1]); | ||
return hydrate_start; | ||
assign_nodes(hydrate_node, null); | ||
return hydrate_node; | ||
} | ||
@@ -49,3 +49,3 @@ | ||
var clone = /** @type {import('#client').TemplateNode} */ ( | ||
var clone = /** @type {TemplateNode} */ ( | ||
use_import_node ? document.importNode(node, true) : node.cloneNode(true) | ||
@@ -55,4 +55,4 @@ ); | ||
if (is_fragment) { | ||
var start = /** @type {import('#client').TemplateNode} */ (clone.firstChild); | ||
var end = /** @type {import('#client').TemplateNode} */ (clone.lastChild); | ||
var start = /** @type {TemplateNode} */ (clone.firstChild); | ||
var end = /** @type {TemplateNode} */ (clone.lastChild); | ||
@@ -114,5 +114,4 @@ assign_nodes(start, end); | ||
if (hydrating) { | ||
assign_nodes(get_start(), hydrate_nodes[hydrate_nodes.length - 1]); | ||
return hydrate_start; | ||
assign_nodes(hydrate_node, null); | ||
return hydrate_node; | ||
} | ||
@@ -134,7 +133,7 @@ | ||
var clone = /** @type {import('#client').TemplateNode} */ (node.cloneNode(true)); | ||
var clone = /** @type {TemplateNode} */ (node.cloneNode(true)); | ||
if (is_fragment) { | ||
var start = /** @type {import('#client').TemplateNode} */ (clone.firstChild); | ||
var end = /** @type {import('#client').TemplateNode} */ (clone.lastChild); | ||
var start = /** @type {TemplateNode} */ (clone.firstChild); | ||
var end = /** @type {TemplateNode} */ (clone.lastChild); | ||
@@ -204,2 +203,3 @@ assign_nodes(start, end); | ||
clone.textContent = script.textContent; | ||
// If node === script tag, replaceWith will do nothing because there's no parent yet, | ||
@@ -217,7 +217,4 @@ // waiting until that's the case using an effect solves this. | ||
/** | ||
* @param {Text | Comment | Element} anchor | ||
*/ | ||
/*#__NO_SIDE_EFFECTS__*/ | ||
export function text(anchor) { | ||
export function text() { | ||
if (!hydrating) { | ||
@@ -229,8 +226,8 @@ var t = empty(); | ||
var node = hydrate_start; | ||
var node = hydrate_node; | ||
if (!node) { | ||
// if an {expression} is empty during SSR, `hydrate_nodes` will be empty. | ||
// we need to insert an empty text node | ||
anchor.before((node = empty())); | ||
if (node.nodeType !== 3) { | ||
// if an {expression} is empty during SSR, we need to insert an empty text node | ||
node.before((node = empty())); | ||
set_hydrate_node(node); | ||
} | ||
@@ -245,5 +242,4 @@ | ||
if (hydrating) { | ||
assign_nodes(get_start(), hydrate_nodes[hydrate_nodes.length - 1]); | ||
return hydrate_start; | ||
assign_nodes(hydrate_node, null); | ||
return hydrate_node; | ||
} | ||
@@ -268,8 +264,14 @@ | ||
export function append(anchor, dom) { | ||
if (hydrating) return; | ||
// We intentionally do not assign the `dom` property of the effect here because it's far too | ||
// late. If we try, we will capture additional DOM elements that we cannot control the lifecycle | ||
// for and will inevitably cause memory leaks. See https://github.com/sveltejs/svelte/pull/11832 | ||
if (hydrating) { | ||
/** @type {Effect & { nodes: EffectNodes }} */ (current_effect).nodes.end = hydrate_node; | ||
hydrate_next(); | ||
return; | ||
} | ||
if (anchor === null) { | ||
// edge case — void `<svelte:element>` with content | ||
return; | ||
} | ||
anchor.before(/** @type {Node} */ (dom)); | ||
} |
@@ -18,2 +18,3 @@ export { add_locations } from './dev/elements.js'; | ||
export { html } from './dom/blocks/html.js'; | ||
export { sanitize_slots, slot } from './dom/blocks/slot.js'; | ||
export { snippet, wrap_snippet } from './dom/blocks/snippet.js'; | ||
@@ -66,2 +67,3 @@ export { component } from './dom/blocks/svelte-component.js'; | ||
export { bind_window_scroll, bind_window_size } from './dom/elements/bindings/window.js'; | ||
export { next, reset } from './dom/hydration.js'; | ||
export { | ||
@@ -123,3 +125,3 @@ once, | ||
} from './reactivity/store.js'; | ||
export { append_styles, sanitize_slots, set_text, slot } from './render.js'; | ||
export { append_styles, set_text } from './render.js'; | ||
export { | ||
@@ -126,0 +128,0 @@ get, |
@@ -39,3 +39,3 @@ import type { ComponentContext, Dom, Equals, TemplateNode, TransitionManager } from '#client'; | ||
start: TemplateNode; | ||
end: TemplateNode; | ||
end: null | TemplateNode; | ||
} | ||
@@ -42,0 +42,0 @@ |
import { DEV } from 'esm-env'; | ||
import { clear_text_content, empty, init_operations } from './dom/operations.js'; | ||
import { HYDRATION_ERROR, HYDRATION_START, PassiveDelegatedEvents } from '../../constants.js'; | ||
import { flush_sync, push, pop, current_component_context } from './runtime.js'; | ||
import { | ||
HYDRATION_END, | ||
HYDRATION_ERROR, | ||
HYDRATION_START, | ||
PassiveDelegatedEvents | ||
} from '../../constants.js'; | ||
import { flush_sync, push, pop, current_component_context, current_effect } from './runtime.js'; | ||
import { effect_root, branch } from './reactivity/effects.js'; | ||
import { | ||
hydrate_anchor, | ||
hydrate_nodes, | ||
set_hydrate_nodes, | ||
hydrate_next, | ||
hydrate_node, | ||
hydrating, | ||
set_hydrate_node, | ||
set_hydrating | ||
@@ -18,2 +24,3 @@ } from './dom/hydration.js'; | ||
import { validate_component } from '../shared/validate.js'; | ||
import { assign_nodes } from './dom/template.js'; | ||
@@ -54,18 +61,2 @@ /** @type {Set<string>} */ | ||
/** | ||
* @param {Comment} anchor | ||
* @param {void | ((anchor: Comment, slot_props: Record<string, unknown>) => void)} slot_fn | ||
* @param {Record<string, unknown>} slot_props | ||
* @param {null | ((anchor: Comment) => void)} fallback_fn | ||
*/ | ||
export function slot(anchor, slot_fn, slot_props, fallback_fn) { | ||
if (slot_fn === undefined) { | ||
if (fallback_fn !== null) { | ||
fallback_fn(anchor); | ||
} | ||
} else { | ||
slot_fn(anchor, slot_props); | ||
} | ||
} | ||
/** | ||
* Mounts a component to the given target and returns the exports and potentially the props (if compiled with `accessors: true`) of the component. | ||
@@ -134,3 +125,3 @@ * Transitions will play during the initial render unless the `intro` option is set to `false`. | ||
const target = options.target; | ||
const previous_hydrate_nodes = hydrate_nodes; | ||
const was_hydrating = hydrating; | ||
@@ -140,19 +131,28 @@ try { | ||
return flush_sync(() => { | ||
set_hydrating(true); | ||
var node = target.firstChild; | ||
var anchor = /** @type {import('#client').TemplateNode} */ (target.firstChild); | ||
while ( | ||
node && | ||
(node.nodeType !== 8 || /** @type {Comment} */ (node).data !== HYDRATION_START) | ||
anchor && | ||
(anchor.nodeType !== 8 || /** @type {Comment} */ (anchor).data !== HYDRATION_START) | ||
) { | ||
node = node.nextSibling; | ||
anchor = /** @type {import('#client').TemplateNode} */ (anchor.nextSibling); | ||
} | ||
if (!node) { | ||
if (!anchor) { | ||
throw HYDRATION_ERROR; | ||
} | ||
const anchor = hydrate_anchor(node); | ||
set_hydrating(true); | ||
set_hydrate_node(/** @type {Comment} */ (anchor)); | ||
hydrate_next(); | ||
const instance = _mount(component, { ...options, anchor }); | ||
if ( | ||
hydrate_node.nodeType !== 8 || | ||
/** @type {Comment} */ (hydrate_node).data !== HYDRATION_END | ||
) { | ||
w.hydration_mismatch(); | ||
throw HYDRATION_ERROR; | ||
} | ||
// flush_sync will run this callback and then synchronously run any pending effects, | ||
@@ -166,2 +166,5 @@ // which don't belong to the hydration phase anymore - therefore reset it here | ||
if (error === HYDRATION_ERROR) { | ||
// TODO it's possible for event listeners to have been added and | ||
// not removed, e.g. with `<svelte:window>` or `<svelte:document>` | ||
if (options.recover === false) { | ||
@@ -181,4 +184,3 @@ e.hydration_failed(); | ||
} finally { | ||
set_hydrating(!!previous_hydrate_nodes); | ||
set_hydrate_nodes(previous_hydrate_nodes); | ||
set_hydrating(was_hydrating); | ||
reset_head_anchor(); | ||
@@ -247,2 +249,6 @@ } | ||
if (hydrating) { | ||
assign_nodes(/** @type {import('#client').TemplateNode} */ (anchor), null); | ||
} | ||
should_intro = intro; | ||
@@ -253,2 +259,8 @@ // @ts-expect-error the public typings are not what the actual function looks like | ||
if (hydrating) { | ||
/** @type {import('#client').Effect & { nodes: import('#client').EffectNodes }} */ ( | ||
current_effect | ||
).nodes.end = hydrate_node; | ||
} | ||
if (context) { | ||
@@ -295,12 +307,2 @@ pop(); | ||
/** | ||
* @param {Record<string, any>} props | ||
* @returns {Record<string, any>} | ||
*/ | ||
export function sanitize_slots(props) { | ||
const sanitized = { ...props.$$slots }; | ||
if (props.children) sanitized.default = props.children; | ||
return sanitized; | ||
} | ||
/** | ||
* @param {Node} target | ||
@@ -307,0 +309,0 @@ * @param {string} style_sheet_id |
@@ -1,11 +0,6 @@ | ||
import { | ||
HYDRATION_ANCHOR, | ||
HYDRATION_END, | ||
HYDRATION_END_ELSE, | ||
HYDRATION_START | ||
} from '../../constants.js'; | ||
import { HYDRATION_END, HYDRATION_START, HYDRATION_START_ELSE } from '../../constants.js'; | ||
export const BLOCK_OPEN = `<!--${HYDRATION_START}-->`; | ||
export const BLOCK_OPEN_ELSE = `<!--${HYDRATION_START_ELSE}-->`; | ||
export const BLOCK_CLOSE = `<!--${HYDRATION_END}-->`; | ||
export const BLOCK_ANCHOR = `<!--${HYDRATION_ANCHOR}-->`; | ||
export const BLOCK_CLOSE_ELSE = `<!--${HYDRATION_END_ELSE}-->`; | ||
export const EMPTY_COMMENT = `<!---->`; |
@@ -13,3 +13,3 @@ import { is_promise, noop } from '../shared/utils.js'; | ||
import { current_component, pop, push } from './context.js'; | ||
import { BLOCK_ANCHOR, BLOCK_CLOSE, BLOCK_OPEN } from './hydration.js'; | ||
import { EMPTY_COMMENT, BLOCK_CLOSE, BLOCK_OPEN } from './hydration.js'; | ||
import { validate_store } from '../shared/validate.js'; | ||
@@ -77,2 +77,4 @@ | ||
export function element(payload, tag, attributes_fn = noop, children_fn = noop) { | ||
payload.out += '<!---->'; | ||
if (tag) { | ||
@@ -86,3 +88,3 @@ payload.out += `<${tag} `; | ||
if (!RawTextElements.includes(tag)) { | ||
payload.out += BLOCK_ANCHOR; | ||
payload.out += EMPTY_COMMENT; | ||
} | ||
@@ -147,5 +149,5 @@ payload.out += `</${tag}>`; | ||
const head_payload = payload.head; | ||
payload.head.out += BLOCK_OPEN; | ||
head_payload.out += BLOCK_OPEN; | ||
fn(head_payload); | ||
payload.head.out += BLOCK_CLOSE; | ||
head_payload.out += BLOCK_CLOSE; | ||
} | ||
@@ -171,6 +173,8 @@ | ||
* @param {() => void} component | ||
* @param {boolean} dynamic | ||
* @returns {void} | ||
*/ | ||
export function css_props(payload, is_html, props, component) { | ||
export function css_props(payload, is_html, props, component, dynamic = false) { | ||
const styles = style_object_to_string(props); | ||
if (is_html) { | ||
@@ -181,3 +185,9 @@ payload.out += `<div style="display: contents; ${styles}">`; | ||
} | ||
if (dynamic) { | ||
payload.out += '<!---->'; | ||
} | ||
component(); | ||
if (is_html) { | ||
@@ -455,7 +465,11 @@ payload.out += `<!----></div>`; | ||
* @param {Record<string, any>} props | ||
* @returns {Record<string, any>} | ||
* @returns {Record<string, boolean>} | ||
*/ | ||
export function sanitize_slots(props) { | ||
const sanitized = { ...props.$$slots }; | ||
if (props.children) sanitized.default = props.children; | ||
/** @type {Record<string, boolean>} */ | ||
const sanitized = {}; | ||
if (props.children) sanitized.default = true; | ||
for (const key in props.$$slots) { | ||
sanitized[key] = true; | ||
} | ||
return sanitized; | ||
@@ -462,0 +476,0 @@ } |
/** @import { Readable, StartStopNotifier, Subscriber, Unsubscriber, Updater, Writable } from './public' */ | ||
/** @import { Invalidator, Stores, StoresValues, SubscribeInvalidateTuple } from './private' */ | ||
/** @import { Stores, StoresValues, SubscribeInvalidateTuple } from './private' */ | ||
import { noop, run_all } from '../internal/shared/utils.js'; | ||
@@ -77,3 +77,3 @@ import { safe_not_equal } from '../internal/client/reactivity/equality.js'; | ||
* @param {Subscriber<T>} run | ||
* @param {Invalidator<T>} [invalidate] | ||
* @param {() => void} [invalidate] | ||
* @returns {Unsubscriber} | ||
@@ -80,0 +80,0 @@ */ |
import { Readable, Subscriber } from './public.js'; | ||
/** Cleanup logic callback. */ | ||
type Invalidator<T> = (value?: T) => void; | ||
/** Pair of subscriber and invalidator. */ | ||
type SubscribeInvalidateTuple<T> = [Subscriber<T>, Invalidator<T>]; | ||
type SubscribeInvalidateTuple<T> = [Subscriber<T>, () => void]; | ||
@@ -16,2 +13,2 @@ /** One or more `Readable`s. */ | ||
export { Invalidator, SubscribeInvalidateTuple, Stores, StoresValues }; | ||
export { SubscribeInvalidateTuple, Stores, StoresValues }; |
@@ -1,3 +0,1 @@ | ||
import type { Invalidator } from './private.js'; | ||
/** Callback to inform of a value updates. */ | ||
@@ -33,3 +31,3 @@ type Subscriber<T> = (value: T) => void; | ||
*/ | ||
subscribe(this: void, run: Subscriber<T>, invalidate?: Invalidator<T>): Unsubscriber; | ||
subscribe(this: void, run: Subscriber<T>, invalidate?: () => void): Unsubscriber; | ||
} | ||
@@ -36,0 +34,0 @@ |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.0.0-next.178'; | ||
export const VERSION = '5.0.0-next.179'; | ||
export const PUBLIC_VERSION = '5'; |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
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
2126413
211
46681