Comparing version 5.0.0-next.262 to 5.0.0-next.263
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.0.0-next.262", | ||
"version": "5.0.0-next.263", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "types": "./types/index.d.ts", |
@@ -1,2 +0,2 @@ | ||
/** @import { VariableDeclarator, Node, Identifier } from 'estree' */ | ||
/** @import { VariableDeclarator, Node, Identifier, AssignmentExpression, LabeledStatement, ExpressionStatement } from 'estree' */ | ||
/** @import { Visitors } from 'zimmerframe' */ | ||
@@ -13,3 +13,7 @@ /** @import { ComponentAnalysis } from '../phases/types.js' */ | ||
import { reset, reset_warning_filter } from '../state.js'; | ||
import { extract_identifiers } from '../utils/ast.js'; | ||
import { | ||
extract_identifiers, | ||
extract_all_identifiers_from_expression, | ||
is_text_attribute | ||
} from '../utils/ast.js'; | ||
import { migrate_svelte_ignore } from '../utils/extract_svelte_ignore.js'; | ||
@@ -27,5 +31,6 @@ import { validate_component_options } from '../validate-options.js'; | ||
* @param {string} source | ||
* @param {{filename?: string}} [options] | ||
* @returns {{ code: string; }} | ||
*/ | ||
export function migrate(source) { | ||
export function migrate(source, { filename } = {}) { | ||
try { | ||
@@ -42,3 +47,3 @@ // Blank CSS, could contain SCSS or similar that needs a preprocessor. | ||
reset_warning_filter(() => false); | ||
reset(source, { filename: 'migrate.svelte' }); | ||
reset(source, { filename: filename ?? 'migrate.svelte' }); | ||
@@ -70,2 +75,3 @@ let parsed = parse(source); | ||
analysis, | ||
filename, | ||
str, | ||
@@ -93,7 +99,10 @@ indent, | ||
passive: analysis.root.unique('passive').name, | ||
nonpassive: analysis.root.unique('nonpassive').name | ||
nonpassive: analysis.root.unique('nonpassive').name, | ||
svelte_self: analysis.root.unique('SvelteSelf').name | ||
}, | ||
legacy_imports: new Set(), | ||
script_insertions: new Set(), | ||
derived_components: new Map() | ||
derived_components: new Map(), | ||
derived_labeled_statements: new Set(), | ||
has_svelte_self: false | ||
}; | ||
@@ -125,3 +134,4 @@ | ||
analysis.uses_rest_props || | ||
analysis.uses_props; | ||
analysis.uses_props || | ||
state.has_svelte_self; | ||
@@ -132,2 +142,10 @@ if (!parsed.instance && need_script) { | ||
if (state.has_svelte_self && filename) { | ||
const file = filename.split('/').pop(); | ||
str.appendRight( | ||
insertion_point, | ||
`\n${indent}import ${state.names.svelte_self} from './${file}';` | ||
); | ||
} | ||
const specifiers = [...state.legacy_imports].map((imported) => { | ||
@@ -202,3 +220,3 @@ const local = state.names[imported]; | ||
if (analysis.uses_props || analysis.uses_rest_props) { | ||
type = `{Record<string, any>}`; | ||
type = `Record<string, any>`; | ||
} else { | ||
@@ -304,4 +322,5 @@ type = `{${state.props | ||
* analysis: ComponentAnalysis; | ||
* filename?: string; | ||
* indent: string; | ||
* props: Array<{ local: string; exported: string; init: string; bindable: boolean; slot_name?: string; optional: boolean; type: string; comment?: string, type_only?: boolean }>; | ||
* props: Array<{ local: string; exported: string; init: string; bindable: boolean; slot_name?: string; optional: boolean; type: string; comment?: string; type_only?: boolean; needs_refine_type?: boolean; }>; | ||
* props_insertion_point: number; | ||
@@ -313,3 +332,5 @@ * has_props_rune: boolean; | ||
* script_insertions: Set<string>; | ||
* derived_components: Map<string, string> | ||
* derived_components: Map<string, string>; | ||
* derived_labeled_statements: Set<LabeledStatement>; | ||
* has_svelte_self: boolean; | ||
* }} State | ||
@@ -362,3 +383,3 @@ */ | ||
}, | ||
VariableDeclaration(node, { state, path }) { | ||
VariableDeclaration(node, { state, path, visit }) { | ||
if (state.scope !== state.analysis.instance.scope) { | ||
@@ -484,6 +505,114 @@ return; | ||
} else { | ||
state.str.prependLeft( | ||
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), | ||
' = $state()' | ||
/** | ||
* @type {AssignmentExpression | undefined} | ||
*/ | ||
let assignment_in_labeled; | ||
/** | ||
* @type {LabeledStatement | undefined} | ||
*/ | ||
let labeled_statement; | ||
// Analyze declaration bindings to see if they're exclusively updated within a single reactive statement | ||
const possible_derived = bindings.every((binding) => | ||
binding.references.every((reference) => { | ||
const declaration = reference.path.find((el) => el.type === 'VariableDeclaration'); | ||
const assignment = reference.path.find((el) => el.type === 'AssignmentExpression'); | ||
const update = reference.path.find((el) => el.type === 'UpdateExpression'); | ||
const labeled = reference.path.find( | ||
(el) => el.type === 'LabeledStatement' && el.label.name === '$' | ||
); | ||
if (assignment && labeled) { | ||
if (assignment_in_labeled) return false; | ||
assignment_in_labeled = /** @type {AssignmentExpression} */ (assignment); | ||
labeled_statement = /** @type {LabeledStatement} */ (labeled); | ||
} | ||
return !update && (declaration || (labeled && assignment) || (!labeled && !assignment)); | ||
}) | ||
); | ||
const labeled_has_single_assignment = | ||
labeled_statement?.body.type === 'BlockStatement' && | ||
labeled_statement.body.body.length === 1; | ||
const is_expression_assignment = | ||
labeled_statement?.body.type === 'ExpressionStatement' && | ||
labeled_statement.body.expression.type === 'AssignmentExpression'; | ||
let should_be_state = false; | ||
if (is_expression_assignment) { | ||
const body = /**@type {ExpressionStatement}*/ (labeled_statement?.body); | ||
const expression = /**@type {AssignmentExpression}*/ (body.expression); | ||
const [, ids] = extract_all_identifiers_from_expression(expression.right); | ||
if (ids.length === 0) { | ||
should_be_state = true; | ||
state.derived_labeled_statements.add( | ||
/** @type {LabeledStatement} */ (labeled_statement) | ||
); | ||
} | ||
} | ||
if ( | ||
!should_be_state && | ||
possible_derived && | ||
assignment_in_labeled && | ||
labeled_statement && | ||
(labeled_has_single_assignment || is_expression_assignment) | ||
) { | ||
// Someone wrote a `$: { ... }` statement which we can turn into a `$derived` | ||
state.str.appendRight( | ||
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), | ||
' = $derived(' | ||
); | ||
visit(assignment_in_labeled.right); | ||
state.str.appendRight( | ||
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), | ||
state.str | ||
.snip( | ||
/** @type {number} */ (assignment_in_labeled.right.start), | ||
/** @type {number} */ (assignment_in_labeled.right.end) | ||
) | ||
.toString() | ||
); | ||
state.str.remove( | ||
/** @type {number} */ (labeled_statement.start), | ||
/** @type {number} */ (labeled_statement.end) | ||
); | ||
state.str.appendRight( | ||
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), | ||
')' | ||
); | ||
state.derived_labeled_statements.add(labeled_statement); | ||
} else { | ||
state.str.prependLeft( | ||
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), | ||
' = $state(' | ||
); | ||
if (should_be_state) { | ||
// someone wrote a `$: foo = ...` statement which we can turn into `let foo = $state(...)` | ||
state.str.appendRight( | ||
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), | ||
state.str | ||
.snip( | ||
/** @type {number} */ ( | ||
/** @type {AssignmentExpression} */ (assignment_in_labeled).right.start | ||
), | ||
/** @type {number} */ ( | ||
/** @type {AssignmentExpression} */ (assignment_in_labeled).right.end | ||
) | ||
) | ||
.toString() | ||
); | ||
state.str.remove( | ||
/** @type {number} */ (/** @type {LabeledStatement} */ (labeled_statement).start), | ||
/** @type {number} */ (/** @type {LabeledStatement} */ (labeled_statement).end) | ||
); | ||
} | ||
state.str.appendRight( | ||
/** @type {number} */ (declarator.id.typeAnnotation?.end ?? declarator.id.end), | ||
')' | ||
); | ||
} | ||
} | ||
@@ -519,2 +648,3 @@ } | ||
if (node.label.name !== '$') return; | ||
if (state.derived_labeled_statements.has(node)) return; | ||
@@ -528,2 +658,5 @@ next(); | ||
const ids = extract_identifiers(node.body.expression.left); | ||
const [, expression_ids] = extract_all_identifiers_from_expression( | ||
node.body.expression.right | ||
); | ||
const bindings = ids.map((id) => state.scope.get(id.name)); | ||
@@ -559,10 +692,20 @@ const reassigned_bindings = bindings.filter((b) => b?.reassigned); | ||
for (const binding of reassigned_bindings) { | ||
if (binding && ids.includes(binding.node)) { | ||
if (binding && (ids.includes(binding.node) || expression_ids.length === 0)) { | ||
const init = | ||
binding.kind === 'state' | ||
? ' = $state()' | ||
: expression_ids.length === 0 | ||
? ` = $state(${state.str.original.substring(/** @type {number} */ (node.body.expression.right.start), node.body.expression.right.end)})` | ||
: ''; | ||
// implicitly-declared variable which we need to make explicit | ||
state.str.prependRight( | ||
state.str.prependLeft( | ||
/** @type {number} */ (node.start), | ||
`let ${binding.node.name}${binding.kind === 'state' ? ' = $state()' : ''};\n${state.indent}` | ||
`let ${binding.node.name}${init};\n${state.indent}` | ||
); | ||
} | ||
} | ||
if (expression_ids.length === 0 && !bindings.some((b) => b?.kind === 'store_sub')) { | ||
state.str.remove(/** @type {number} */ (node.start), /** @type {number} */ (node.end)); | ||
return; | ||
} | ||
} | ||
@@ -605,3 +748,4 @@ } | ||
}, | ||
RegularElement(node, { state, next }) { | ||
RegularElement(node, { state, path, next }) { | ||
migrate_slot_usage(node, path, state); | ||
handle_events(node, state); | ||
@@ -619,3 +763,40 @@ // Strip off any namespace from the beginning of the node name. | ||
}, | ||
SvelteElement(node, { state, next }) { | ||
SvelteSelf(node, { state, next }) { | ||
const source = state.str.original.substring(node.start, node.end); | ||
if (!state.filename) { | ||
const indent = guess_indent(source); | ||
state.str.prependRight( | ||
node.start, | ||
`<!-- @migration-task: svelte:self is deprecated, import this Svelte file into itself instead -->\n${indent}` | ||
); | ||
next(); | ||
return; | ||
} | ||
// overwrite the open tag | ||
state.str.overwrite( | ||
node.start + 1, | ||
node.start + 1 + 'svelte:self'.length, | ||
`${state.names.svelte_self}` | ||
); | ||
// if it has a fragment we need to overwrite the closing tag too | ||
if (node.fragment.nodes.length > 0) { | ||
state.str.overwrite( | ||
state.str.original.lastIndexOf('<', node.end) + 2, | ||
node.end - 1, | ||
`${state.names.svelte_self}` | ||
); | ||
} else if (!source.endsWith('/>')) { | ||
// special case for case `<svelte:self></svelte:self>` it has no fragment but | ||
// we still need to overwrite the end tag | ||
state.str.overwrite( | ||
node.start + source.lastIndexOf('</', node.end) + 2, | ||
node.end - 1, | ||
`${state.names.svelte_self}` | ||
); | ||
} | ||
state.has_svelte_self = true; | ||
next(); | ||
}, | ||
SvelteElement(node, { state, path, next }) { | ||
migrate_slot_usage(node, path, state); | ||
if (node.tag.type === 'Literal') { | ||
@@ -644,5 +825,11 @@ let is_static = true; | ||
}, | ||
Component(node, { state, path, next }) { | ||
next(); | ||
migrate_slot_usage(node, path, state); | ||
}, | ||
SvelteComponent(node, { state, next, path }) { | ||
next(); | ||
migrate_slot_usage(node, path, state); | ||
let expression = state.str | ||
@@ -686,3 +873,3 @@ .snip( | ||
); | ||
state.str.prependLeft( | ||
state.str.appendRight( | ||
position, | ||
@@ -714,2 +901,6 @@ `{@const ${expression} = ${current_expression}}\n${indent}` | ||
}, | ||
SvelteFragment(node, { state, path, next }) { | ||
migrate_slot_usage(node, path, state); | ||
next(); | ||
}, | ||
SvelteWindow(node, { state, next }) { | ||
@@ -727,3 +918,5 @@ handle_events(node, state); | ||
}, | ||
SlotElement(node, { state, next }) { | ||
SlotElement(node, { state, path, next, visit }) { | ||
migrate_slot_usage(node, path, state); | ||
if (state.analysis.custom_element) return; | ||
@@ -743,9 +936,18 @@ let name = 'children'; | ||
attr.value === true || Array.isArray(attr.value) ? attr.value : [attr.value]; | ||
const value = | ||
attr_value !== true | ||
? state.str.original.substring( | ||
attr_value[0].start, | ||
attr_value[attr_value.length - 1].end | ||
) | ||
: 'true'; | ||
let value = 'true'; | ||
if (attr_value !== true) { | ||
const first = attr_value[0]; | ||
const last = attr_value[attr_value.length - 1]; | ||
for (const attr of attr_value) { | ||
visit(attr); | ||
} | ||
value = state.str | ||
.snip( | ||
first.type === 'Text' | ||
? first.start - 1 | ||
: /** @type {number} */ (first.expression.start), | ||
last.type === 'Text' ? last.end + 1 : /** @type {number} */ (last.expression.end) | ||
) | ||
.toString(); | ||
} | ||
slot_props += value === attr.name ? `${value}, ` : `${attr.name}: ${value}, `; | ||
@@ -778,2 +980,5 @@ } | ||
}); | ||
} else if (existing_prop.needs_refine_type) { | ||
existing_prop.type = `import('svelte').${slot_props ? 'Snippet<[any]>' : 'Snippet'}`; | ||
existing_prop.needs_refine_type = false; | ||
} | ||
@@ -786,7 +991,11 @@ | ||
node.fragment.nodes[0].start, | ||
`{#if ${name}}{@render ${name}(${slot_props})}{:else}` | ||
`{#if ${name}}{@render ${state.analysis.uses_props ? `${state.names.props}.` : ''}${name}(${slot_props})}{:else}` | ||
); | ||
state.str.update(node.fragment.nodes[node.fragment.nodes.length - 1].end, node.end, '{/if}'); | ||
} else { | ||
state.str.update(node.start, node.end, `{@render ${name}?.(${slot_props})}`); | ||
state.str.update( | ||
node.start, | ||
node.end, | ||
`{@render ${state.analysis.uses_props ? `${state.names.props}.` : ''}${name}?.(${slot_props})}` | ||
); | ||
} | ||
@@ -803,2 +1012,125 @@ }, | ||
/** | ||
* @param {AST.RegularElement | AST.SvelteElement | AST.SvelteComponent | AST.Component | AST.SlotElement | AST.SvelteFragment} node | ||
* @param {SvelteNode[]} path | ||
* @param {State} state | ||
*/ | ||
function migrate_slot_usage(node, path, state) { | ||
const parent = path.at(-2); | ||
// Bail on custom element slot usage | ||
if ( | ||
parent?.type !== 'Component' && | ||
parent?.type !== 'SvelteComponent' && | ||
node.type !== 'Component' && | ||
node.type !== 'SvelteComponent' | ||
) { | ||
return; | ||
} | ||
let snippet_name = 'children'; | ||
let snippet_props = []; | ||
for (let attribute of node.attributes) { | ||
if ( | ||
attribute.type === 'Attribute' && | ||
attribute.name === 'slot' && | ||
is_text_attribute(attribute) | ||
) { | ||
snippet_name = attribute.value[0].data; | ||
state.str.remove(attribute.start, attribute.end); | ||
} | ||
if (attribute.type === 'LetDirective') { | ||
snippet_props.push( | ||
attribute.name + | ||
(attribute.expression | ||
? `: ${state.str.original.substring(/** @type {number} */ (attribute.expression.start), /** @type {number} */ (attribute.expression.end))}` | ||
: '') | ||
); | ||
state.str.remove(attribute.start, attribute.end); | ||
} | ||
} | ||
if (node.type === 'SvelteFragment' && node.fragment.nodes.length > 0) { | ||
// remove node itself, keep content | ||
state.str.remove(node.start, node.fragment.nodes[0].start); | ||
state.str.remove(node.fragment.nodes[node.fragment.nodes.length - 1].end, node.end); | ||
} | ||
const props = snippet_props.length > 0 ? `{ ${snippet_props.join(', ')} }` : ''; | ||
if (snippet_name === 'children' && node.type !== 'SvelteFragment') { | ||
if (snippet_props.length === 0) return; // nothing to do | ||
let inner_start = 0; | ||
let inner_end = 0; | ||
for (let i = 0; i < node.fragment.nodes.length; i++) { | ||
const inner = node.fragment.nodes[i]; | ||
const is_empty_text = inner.type === 'Text' && !inner.data.trim(); | ||
if ( | ||
(inner.type === 'RegularElement' || | ||
inner.type === 'SvelteElement' || | ||
inner.type === 'Component' || | ||
inner.type === 'SvelteComponent' || | ||
inner.type === 'SlotElement' || | ||
inner.type === 'SvelteFragment') && | ||
inner.attributes.some((attr) => attr.type === 'Attribute' && attr.name === 'slot') | ||
) { | ||
if (inner_start && !inner_end) { | ||
// End of default slot content | ||
inner_end = inner.start; | ||
} | ||
} else if (!inner_start && !is_empty_text) { | ||
// Start of default slot content | ||
inner_start = inner.start; | ||
} else if (inner_end && !is_empty_text) { | ||
// There was default slot content before, then some named slot content, now some default slot content again. | ||
// We're moving the last character back by one to avoid the closing {/snippet} tag inserted afterwards | ||
// to come before the opening {#snippet} tag of the named slot. | ||
state.str.update(inner_end - 1, inner_end, ''); | ||
state.str.prependLeft(inner_end - 1, state.str.original[inner_end - 1]); | ||
state.str.move(inner.start, inner.end, inner_end - 1); | ||
} | ||
} | ||
if (!inner_end) { | ||
inner_end = node.fragment.nodes[node.fragment.nodes.length - 1].end; | ||
} | ||
state.str.appendLeft( | ||
inner_start, | ||
`{#snippet ${snippet_name}(${props})}\n${state.indent.repeat(path.length)}` | ||
); | ||
state.str.indent(state.indent, { | ||
exclude: [ | ||
[0, inner_start], | ||
[inner_end, state.str.original.length] | ||
] | ||
}); | ||
if (inner_end < node.fragment.nodes[node.fragment.nodes.length - 1].end) { | ||
// Named slots coming afterwards | ||
state.str.prependLeft(inner_end, `{/snippet}\n${state.indent.repeat(path.length)}`); | ||
} else { | ||
// No named slots coming afterwards | ||
state.str.prependLeft( | ||
inner_end, | ||
`${state.indent.repeat(path.length)}{/snippet}\n${state.indent.repeat(path.length - 1)}` | ||
); | ||
} | ||
} else { | ||
// Named slot or `svelte:fragment`: wrap element itself in a snippet | ||
state.str.prependLeft( | ||
node.start, | ||
`{#snippet ${snippet_name}(${props})}\n${state.indent.repeat(path.length - 2)}` | ||
); | ||
state.str.indent(state.indent, { | ||
exclude: [ | ||
[0, node.start], | ||
[node.end, state.str.original.length] | ||
] | ||
}); | ||
state.str.appendLeft(node.end, `\n${state.indent.repeat(path.length - 2)}{/snippet}`); | ||
} | ||
} | ||
/** | ||
* @param {VariableDeclarator} declarator | ||
@@ -986,3 +1318,3 @@ * @param {MagicString} str | ||
if (state.analysis.uses_props) { | ||
if (state.analysis.uses_props && node.name !== '$$slots') { | ||
if (node.name === '$$props' || node.name === '$$restProps') { | ||
@@ -1009,6 +1341,38 @@ // not 100% correct for $$restProps but it'll do | ||
if (parent?.type === 'MemberExpression') { | ||
state.str.update(/** @type {number} */ (node.start), parent.property.start, ''); | ||
if (parent.property.name === 'default') { | ||
state.str.update(parent.property.start, parent.property.end, 'children'); | ||
if (state.analysis.custom_element) return; | ||
let name = parent.property.type === 'Literal' ? parent.property.value : parent.property.name; | ||
let slot_name = name; | ||
const existing_prop = state.props.find((prop) => prop.slot_name === name); | ||
if (existing_prop) { | ||
name = existing_prop.local; | ||
} else if (name !== 'default') { | ||
name = state.scope.generate(name); | ||
} | ||
name = name === 'default' ? 'children' : name; | ||
if (!existing_prop) { | ||
state.props.push({ | ||
local: name, | ||
exported: name, | ||
init: '', | ||
bindable: false, | ||
optional: true, | ||
slot_name, | ||
// if it's the first time we encounter this slot | ||
// we start with any and delegate to when the slot | ||
// is actually rendered (it might not happen in that case) | ||
// any is still a safe bet | ||
type: `import('svelte').Snippet<[any]>}`, | ||
needs_refine_type: true | ||
}); | ||
} | ||
state.str.update( | ||
/** @type {number} */ (node.start), | ||
parent.property.start, | ||
state.analysis.uses_props ? `${state.names.props}.` : '' | ||
); | ||
state.str.update(parent.property.start, parent.end, name); | ||
} | ||
@@ -1015,0 +1379,0 @@ // else passed as identifier, we don't know what to do here, so let it error |
@@ -401,3 +401,6 @@ /** @import { EachItem, EachState, Effect, MaybeSource, Source, TemplateNode, TransitionManager, Value } from '#client' */ | ||
while (current !== null) { | ||
to_destroy.push(current); | ||
// Inert effects are currently outroing and will be removed once the transition is finished | ||
if ((current.e.f & INERT) === 0) { | ||
to_destroy.push(current); | ||
} | ||
current = current.next; | ||
@@ -404,0 +407,0 @@ } |
@@ -141,8 +141,6 @@ import { hydrating } from '../../hydration.js'; | ||
export function bind_paused(media, get, set = get) { | ||
var mounted = hydrating; | ||
var paused = get(); | ||
var callback = () => { | ||
var update = () => { | ||
if (paused !== media.paused) { | ||
paused = media.paused; | ||
set((paused = media.paused)); | ||
@@ -152,42 +150,16 @@ } | ||
if (paused == null) { | ||
callback(); | ||
} | ||
// If someone switches the src while media is playing, the player will pause. | ||
// Listen to the canplay event to get notified of this situation. | ||
listen(media, ['play', 'pause', 'canplay'], update, paused == null); | ||
// Defer listening if not mounted yet so that the first canplay event doesn't cause a potentially wrong update | ||
if (mounted) { | ||
// If someone switches the src while media is playing, the player will pause. | ||
// Listen to the canplay event to get notified of this situation. | ||
listen(media, ['play', 'pause', 'canplay'], callback, false); | ||
} | ||
render_effect(() => { | ||
paused = !!get(); | ||
if (paused !== media.paused) { | ||
var toggle = () => { | ||
mounted = true; | ||
if (paused) { | ||
media.pause(); | ||
} else { | ||
media.play().catch(() => { | ||
set((paused = true)); | ||
}); | ||
} | ||
}; | ||
if (mounted) { | ||
toggle(); | ||
// Needs to be an effect to ensure media element is mounted: else, if paused is `false` (i.e. should play right away) | ||
// a "The play() request was interrupted by a new load request" error would be thrown because the resource isn't loaded yet. | ||
effect(() => { | ||
if ((paused = !!get()) !== media.paused) { | ||
if (paused) { | ||
media.pause(); | ||
} else { | ||
// If this is the first invocation in dom mode, the media element isn't mounted yet, | ||
// and therefore its resource isn't loaded yet. We need to wait for the canplay event | ||
// in this case or else we'll get a "The play() request was interrupted by a new load request" error. | ||
media.addEventListener( | ||
'canplay', | ||
() => { | ||
listen(media, ['play', 'pause', 'canplay'], callback, false); | ||
toggle(); | ||
}, | ||
{ once: true } | ||
); | ||
media.play().catch(() => { | ||
set((paused = true)); | ||
}); | ||
} | ||
@@ -194,0 +166,0 @@ } |
@@ -410,2 +410,6 @@ /** @import { ComponentContext, ComponentContextLegacy, Derived, Effect, Reaction, TemplateNode, TransitionManager } from '#client' */ | ||
if (DEV) { | ||
effect.component_function = null; | ||
} | ||
// `first` and `child` are nulled out in destroy_effect_children | ||
@@ -412,0 +416,0 @@ effect.next = |
@@ -51,1 +51,17 @@ /** @import { SvelteComponent } from '../index.js' */ | ||
} | ||
const noop = () => {}; | ||
// event stuff, no need to worry about it for SSR but needs to be there or it will crash | ||
export { | ||
noop as handlers, | ||
noop as createBubbler, | ||
noop as once, | ||
noop as preventDefault, | ||
noop as self, | ||
noop as stopImmediatePropagation, | ||
noop as stopPropagation, | ||
noop as trusted, | ||
noop as passive, | ||
noop as nonpassive | ||
}; |
/** @import { Source } from '#client' */ | ||
import { DESTROYED } from '../internal/client/constants.js'; | ||
import { derived } from '../internal/client/index.js'; | ||
@@ -45,3 +46,3 @@ import { source, set } from '../internal/client/reactivity/sources.js'; | ||
if (d === undefined) { | ||
if (d === undefined || (d.f & DESTROYED) !== 0) { | ||
d = derived(() => { | ||
@@ -48,0 +49,0 @@ get(this.#time); |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.0.0-next.262'; | ||
export const VERSION = '5.0.0-next.263'; | ||
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 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
2251833
49567