svelte
Advanced tools
Comparing version 5.0.0-next.175 to 5.0.0-next.176
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.0.0-next.175", | ||
"version": "5.0.0-next.176", | ||
"type": "module", | ||
@@ -150,3 +150,3 @@ "types": "./types/index.d.ts", | ||
"dev": "node scripts/process-messages && rollup -cw", | ||
"check": "tsc && cd ./tests/types && tsc", | ||
"check": "tsc --project tsconfig.runtime.json && tsc && cd ./tests/types && tsc", | ||
"check:watch": "tsc --watch", | ||
@@ -153,0 +153,0 @@ "generate:version": "node ./scripts/generate-version.js", |
/* This file is generated by scripts/process-messages/index.js. Do not edit! */ | ||
/** @import { Location } from 'locate-character' */ | ||
import * as state from './state.js'; | ||
import { CompileDiagnostic } from './utils/compile_diagnostic.js'; | ||
/** @typedef {{ start?: number, end?: number }} NodeLike */ | ||
export class InternalCompileError extends Error { | ||
export class InternalCompileError extends CompileDiagnostic { | ||
name = 'CompileError'; | ||
filename = state.filename; | ||
/** @type {[number, number] | undefined} */ | ||
position = undefined; | ||
/** @type {Location | undefined} */ | ||
start = undefined; | ||
/** @type {Location | undefined} */ | ||
end = undefined; | ||
/** | ||
* | ||
* @param {string} code | ||
@@ -24,27 +15,4 @@ * @param {string} message | ||
constructor(code, message, position) { | ||
super(message); | ||
this.code = code; | ||
this.position = position; | ||
if (position) { | ||
this.start = state.locator(position[0]); | ||
this.end = state.locator(position[1]); | ||
} | ||
super(code, message, position); | ||
} | ||
toString() { | ||
let out = `${this.name}: ${this.message}`; | ||
out += `\n(${this.code})`; | ||
if (this.filename) { | ||
out += `\n${this.filename}`; | ||
if (this.start) { | ||
out += `${this.start.line}:${this.start.column}`; | ||
} | ||
} | ||
return out; | ||
} | ||
} | ||
@@ -62,3 +30,3 @@ | ||
throw new InternalCompileError(code, message, start !== undefined && end !== undefined ? [start, end] : undefined); | ||
throw new InternalCompileError(code, message, start !== undefined ? [start, end ?? start] : undefined); | ||
} | ||
@@ -65,0 +33,0 @@ |
@@ -356,2 +356,3 @@ /** @import { Expression } from 'estree' */ | ||
const start = node.elseif ? node.consequent.nodes[0].start : node.start; | ||
remove_surrounding_whitespace_nodes(node.consequent.nodes); | ||
@@ -361,3 +362,3 @@ | ||
type: 'IfBlock', | ||
start: node.start, | ||
start, | ||
end: node.end, | ||
@@ -364,0 +365,0 @@ expression: node.test, |
@@ -148,2 +148,43 @@ /** @import { VariableDeclarator, Node, Identifier } from 'estree' */ | ||
/** | ||
* If true, then we need to move all reactive statements to the end of the script block, | ||
* in their correct order. Svelte 4 reordered reactive statements, $derived/$effect.pre | ||
* don't have this behavior. | ||
*/ | ||
let needs_reordering = false; | ||
for (const [node, { dependencies }] of state.analysis.reactive_statements) { | ||
/** @type {Compiler.Binding[]} */ | ||
let ids = []; | ||
if ( | ||
node.body.type === 'ExpressionStatement' && | ||
node.body.expression.type === 'AssignmentExpression' | ||
) { | ||
ids = extract_identifiers(node.body.expression.left) | ||
.map((id) => state.scope.get(id.name)) | ||
.filter((id) => !!id); | ||
} | ||
if ( | ||
dependencies.some( | ||
(dep) => | ||
!ids.includes(dep) && | ||
/** @type {number} */ (dep.node.start) > /** @type {number} */ (node.start) | ||
) | ||
) { | ||
needs_reordering = true; | ||
break; | ||
} | ||
} | ||
if (needs_reordering) { | ||
const nodes = Array.from(state.analysis.reactive_statements.keys()); | ||
for (const node of nodes) { | ||
const { start, end } = get_node_range(source, node); | ||
str.appendLeft(end, '\n'); | ||
str.move(start, end, /** @type {number} */ (parsed.instance?.content.end)); | ||
str.remove(start - (source[start - 2] === '\r' ? 2 : 1), start); | ||
} | ||
} | ||
if (state.needs_run && !added_legacy_import) { | ||
@@ -381,3 +422,3 @@ if (parsed.instance) { | ||
); | ||
state.str.prependLeft( | ||
state.str.prependRight( | ||
/** @type {number} */ (node.body.expression.right.start), | ||
@@ -393,3 +434,3 @@ '$derived(' | ||
} else { | ||
state.str.appendRight(/** @type {number} */ (node.end), ');'); | ||
state.str.appendLeft(/** @type {number} */ (node.end), ');'); | ||
} | ||
@@ -401,3 +442,3 @@ return; | ||
// implicitly-declared variable which we need to make explicit | ||
state.str.prependLeft( | ||
state.str.prependRight( | ||
/** @type {number} */ (node.start), | ||
@@ -435,3 +476,3 @@ `let ${binding.node.name}${binding.kind === 'state' ? ' = $state()' : ''};\n${state.indent}` | ||
}); | ||
state.str.appendRight(/** @type {number} */ (node.end), `\n${state.indent}});`); | ||
state.str.appendLeft(/** @type {number} */ (node.end), `\n${state.indent}});`); | ||
} | ||
@@ -817,2 +858,26 @@ } | ||
/** | ||
* Returns start and end of the node. If the start is preceeded with white-space-only before a line break, | ||
* the start will be the start of the line. | ||
* @param {string} source | ||
* @param {Node} node | ||
*/ | ||
function get_node_range(source, node) { | ||
let start = /** @type {number} */ (node.start); | ||
let end = /** @type {number} */ (node.end); | ||
let idx = start; | ||
while (source[idx - 1] !== '\n' && source[idx - 1] !== '\r') { | ||
idx--; | ||
if (source[idx] !== ' ' && source[idx] !== '\t') { | ||
idx = start; | ||
break; | ||
} | ||
} | ||
start = idx; | ||
return { start, end }; | ||
} | ||
/** | ||
* @param {Compiler.OnDirective} last | ||
@@ -819,0 +884,0 @@ * @param {State} state |
@@ -6,3 +6,3 @@ /** @import { TemplateNode, Fragment, Root, SvelteOptionsRaw } from '#compiler' */ | ||
import { regex_whitespace } from '../patterns.js'; | ||
import { reserved } from './utils/names.js'; | ||
import { reserved } from '../../../constants.js'; | ||
import full_char_code_at from './utils/full_char_code_at.js'; | ||
@@ -9,0 +9,0 @@ import * as e from '../../errors.js'; |
/** @import { Parser } from '../index.js' */ | ||
/** @import * as Compiler from '#compiler' */ | ||
import { is_void } from '../utils/names.js'; | ||
import { is_void } from '../../../../constants.js'; | ||
import read_expression from '../read/expression.js'; | ||
@@ -5,0 +5,0 @@ import { read_script } from '../read/script.js'; |
@@ -348,3 +348,3 @@ import read_pattern from '../read/context.js'; | ||
const child = parser.append({ | ||
start: parser.index, | ||
start: start - 1, | ||
end: -1, | ||
@@ -351,0 +351,0 @@ type: 'IfBlock', |
@@ -11,3 +11,3 @@ import type { | ||
import type { ComponentAnalysis } from '../../types.js'; | ||
import type { Location } from 'locate-character'; | ||
import type { SourceLocation } from '#shared'; | ||
@@ -28,6 +28,2 @@ export interface ClientTransformState extends TransformState { | ||
export type SourceLocation = | ||
| [line: number, column: number] | ||
| [line: number, column: number, SourceLocation[]]; | ||
export interface ComponentClientTransformState extends ClientTransformState { | ||
@@ -34,0 +30,0 @@ readonly analysis: ComponentAnalysis; |
@@ -17,2 +17,8 @@ /** @import { SvelteNode } from './types' */ | ||
/** | ||
* The original source code | ||
* @type {string} | ||
*/ | ||
export let source; | ||
export let locator = getLocator('', { offsetLine: 1 }); | ||
@@ -47,6 +53,7 @@ | ||
/** | ||
* @param {string} source | ||
* @param {string} _source | ||
* @param {{ filename?: string, rootDir?: string }} options | ||
*/ | ||
export function reset(source, options) { | ||
export function reset(_source, options) { | ||
source = _source; | ||
const root_dir = options.rootDir?.replace(/\\/g, '/'); | ||
@@ -53,0 +60,0 @@ filename = options.filename?.replace(/\\/g, '/'); |
@@ -9,3 +9,2 @@ import type { | ||
} from 'estree'; | ||
import type { Location } from 'locate-character'; | ||
import type { SourceMap } from 'magic-string'; | ||
@@ -16,3 +15,3 @@ import type { Context } from 'zimmerframe'; | ||
import type { EachBlock, Namespace, SvelteNode, SvelteOptions } from './template.js'; | ||
import type { InternalCompileError } from '../errors.js'; | ||
import type { ICompileDiagnostic } from '../utils/compile_diagnostic.js'; | ||
@@ -56,12 +55,5 @@ /** The return value of `compile` from `svelte/compiler` */ | ||
export interface Warning { | ||
start?: Location; | ||
end?: Location; | ||
// TODO there was pos: number in Svelte 4 - do we want to add it back? | ||
code: string; | ||
message: string; | ||
filename?: string; | ||
} | ||
export interface Warning extends ICompileDiagnostic {} | ||
export interface CompileError extends InternalCompileError {} | ||
export interface CompileError extends ICompileDiagnostic {} | ||
@@ -68,0 +60,0 @@ export type CssHashGetter = (args: { |
/* This file is generated by scripts/process-messages/index.js. Do not edit! */ | ||
import { | ||
filename, | ||
locator, | ||
warnings, | ||
ignore_stack, | ||
ignore_map | ||
} from './state.js'; | ||
import { warnings, ignore_stack, ignore_map } from './state.js'; | ||
import { CompileDiagnostic } from './utils/compile_diagnostic.js'; | ||
/** @typedef {{ start?: number, end?: number }} NodeLike */ | ||
export class InternalCompileWarning extends CompileDiagnostic { | ||
name = 'CompileWarning'; | ||
/** | ||
* @param {string} code | ||
* @param {string} message | ||
* @param {[number, number] | undefined} position | ||
*/ | ||
constructor(code, message, position) { | ||
super(code, message, position); | ||
} | ||
} | ||
/** | ||
@@ -25,10 +33,3 @@ * @param {null | NodeLike} node | ||
if (stack && stack.at(-1)?.has(code)) return; | ||
warnings.push({ | ||
code, | ||
message, | ||
filename, | ||
start: node?.start !== undefined ? locator(node.start) : undefined, | ||
end: node?.end !== undefined ? locator(node.end) : undefined | ||
}); | ||
warnings.push(new InternalCompileWarning(code, message, node && node.start !== undefined ? [node.start, node.end ?? node.start] : undefined)); | ||
} | ||
@@ -35,0 +36,0 @@ |
@@ -296,1 +296,76 @@ export const EACH_ITEM_REACTIVE = 1; | ||
} | ||
export const reserved = [ | ||
'arguments', | ||
'await', | ||
'break', | ||
'case', | ||
'catch', | ||
'class', | ||
'const', | ||
'continue', | ||
'debugger', | ||
'default', | ||
'delete', | ||
'do', | ||
'else', | ||
'enum', | ||
'eval', | ||
'export', | ||
'extends', | ||
'false', | ||
'finally', | ||
'for', | ||
'function', | ||
'if', | ||
'implements', | ||
'import', | ||
'in', | ||
'instanceof', | ||
'interface', | ||
'let', | ||
'new', | ||
'null', | ||
'package', | ||
'private', | ||
'protected', | ||
'public', | ||
'return', | ||
'static', | ||
'super', | ||
'switch', | ||
'this', | ||
'throw', | ||
'true', | ||
'try', | ||
'typeof', | ||
'var', | ||
'void', | ||
'while', | ||
'with', | ||
'yield' | ||
]; | ||
const void_element_names = [ | ||
'area', | ||
'base', | ||
'br', | ||
'col', | ||
'command', | ||
'embed', | ||
'hr', | ||
'img', | ||
'input', | ||
'keygen', | ||
'link', | ||
'meta', | ||
'param', | ||
'source', | ||
'track', | ||
'wbr' | ||
]; | ||
/** @param {string} name */ | ||
export function is_void(name) { | ||
return void_element_names.includes(name) || name.toLowerCase() === '!doctype'; | ||
} |
@@ -1,2 +0,2 @@ | ||
/** @import { SourceLocation } from '../../../compiler/phases/3-transform/client/types.js' */ | ||
/** @import { SourceLocation } from '#shared' */ | ||
import { HYDRATION_END, HYDRATION_START } from '../../../constants.js'; | ||
@@ -3,0 +3,0 @@ import { hydrating } from '../dom/hydration.js'; |
@@ -0,1 +1,2 @@ | ||
/** @import { Effect, Source, TemplateNode } from '#client' */ | ||
import { is_promise, noop } from '../../../shared/utils.js'; | ||
@@ -23,6 +24,6 @@ import { | ||
* @template V | ||
* @param {Comment} anchor | ||
* @param {TemplateNode} anchor | ||
* @param {(() => Promise<V>)} get_input | ||
* @param {null | ((anchor: Node) => void)} pending_fn | ||
* @param {null | ((anchor: Node, value: import('#client').Source<V>) => void)} then_fn | ||
* @param {null | ((anchor: Node, value: Source<V>) => void)} then_fn | ||
* @param {null | ((anchor: Node, error: unknown) => void)} catch_fn | ||
@@ -41,9 +42,9 @@ * @returns {void} | ||
/** @type {import('#client').Effect | null} */ | ||
/** @type {Effect | null} */ | ||
var pending_effect; | ||
/** @type {import('#client').Effect | null} */ | ||
/** @type {Effect | null} */ | ||
var then_effect; | ||
/** @type {import('#client').Effect | null} */ | ||
/** @type {Effect | null} */ | ||
var catch_effect; | ||
@@ -50,0 +51,0 @@ |
@@ -0,3 +1,4 @@ | ||
/** @import { TemplateNode } from '#client' */ | ||
import { hydrating, set_hydrate_nodes } from '../hydration.js'; | ||
import { render_effect } from '../../reactivity/effects.js'; | ||
import { render_effect, teardown } from '../../reactivity/effects.js'; | ||
@@ -11,27 +12,22 @@ /** | ||
if (hydrating) { | ||
set_hydrate_nodes( | ||
/** @type {import('#client').TemplateNode[]} */ ([...element.childNodes]).slice(0, -1) | ||
); | ||
set_hydrate_nodes(/** @type {TemplateNode[]} */ ([...element.childNodes]).slice(0, -1)); | ||
} | ||
render_effect(() => { | ||
render_effect(() => { | ||
var styles = get_styles(); | ||
var styles = get_styles(); | ||
for (var key in styles) { | ||
var value = styles[key]; | ||
for (var key in styles) { | ||
var value = styles[key]; | ||
if (value) { | ||
element.style.setProperty(key, value); | ||
} else { | ||
element.style.removeProperty(key); | ||
} | ||
if (value) { | ||
element.style.setProperty(key, value); | ||
} else { | ||
element.style.removeProperty(key); | ||
} | ||
}); | ||
} | ||
}); | ||
return () => { | ||
// TODO use `teardown` instead of creating a nested effect, post-https://github.com/sveltejs/svelte/pull/11936 | ||
element.remove(); | ||
}; | ||
teardown(() => { | ||
element.remove(); | ||
}); | ||
} |
@@ -0,1 +1,2 @@ | ||
/** @import { Effect, TemplateNode } from '#client' */ | ||
import { block, branch, destroy_effect } from '../../reactivity/effects.js'; | ||
@@ -16,3 +17,3 @@ import { get_start, hydrate_nodes, hydrating } from '../hydration.js'; | ||
/** @type {import('#client').Effect | null} */ | ||
/** @type {Effect | null} */ | ||
var effect; | ||
@@ -50,4 +51,4 @@ | ||
assign_nodes( | ||
/** @type {import('#client').TemplateNode} */ (node.firstChild), | ||
/** @type {import('#client').TemplateNode} */ (node.lastChild) | ||
/** @type {TemplateNode} */ (node.firstChild), | ||
/** @type {TemplateNode} */ (node.lastChild) | ||
); | ||
@@ -54,0 +55,0 @@ |
@@ -0,1 +1,2 @@ | ||
/** @import { Effect, TemplateNode } from '#client' */ | ||
import { add_snippet_symbol } from '../../../shared/validate.js'; | ||
@@ -10,4 +11,4 @@ import { EFFECT_TRANSPARENT } from '../../constants.js'; | ||
/** | ||
* @template {(node: import('#client').TemplateNode, ...args: any[]) => import('#client').Dom} SnippetFn | ||
* @param {import('#client').TemplateNode} anchor | ||
* @template {(node: TemplateNode, ...args: any[]) => void} SnippetFn | ||
* @param {TemplateNode} anchor | ||
* @param {() => SnippetFn | null | undefined} get_snippet | ||
@@ -21,3 +22,3 @@ * @param {(() => any)[]} args | ||
/** @type {import('#client').Effect | null} */ | ||
/** @type {Effect | null} */ | ||
var snippet_effect; | ||
@@ -42,18 +43,16 @@ | ||
* correct component context is set for ownership checks | ||
* @param {(node: import('#client').TemplateNode, ...args: any[]) => import('#client').Dom} fn | ||
* @param {any} component | ||
* @param {(node: TemplateNode, ...args: any[]) => void} fn | ||
*/ | ||
export function wrap_snippet(fn, component) { | ||
return add_snippet_symbol( | ||
(/** @type {import('#client').TemplateNode} */ node, /** @type {any[]} */ ...args) => { | ||
var previous_component_function = dev_current_component_function; | ||
set_dev_current_component_function(component); | ||
export function wrap_snippet(component, fn) { | ||
return add_snippet_symbol((/** @type {TemplateNode} */ node, /** @type {any[]} */ ...args) => { | ||
var previous_component_function = dev_current_component_function; | ||
set_dev_current_component_function(component); | ||
try { | ||
return fn(node, ...args); | ||
} finally { | ||
set_dev_current_component_function(previous_component_function); | ||
} | ||
try { | ||
return fn(node, ...args); | ||
} finally { | ||
set_dev_current_component_function(previous_component_function); | ||
} | ||
); | ||
}); | ||
} |
@@ -17,2 +17,3 @@ import { namespace_svg } from '../../../../constants.js'; | ||
import { noop } from '../../../shared/utils.js'; | ||
import { EFFECT_TRANSPARENT } from '../../constants.js'; | ||
@@ -73,3 +74,2 @@ /** | ||
current_tag = null; | ||
element?.remove(); | ||
}); | ||
@@ -88,3 +88,2 @@ } else if (next_tag === current_tag) { | ||
effect = branch(() => { | ||
const prev_element = element; | ||
element = hydrating | ||
@@ -109,6 +108,2 @@ ? /** @type {Element} */ (element) | ||
if (prev_element && !hydrating) { | ||
prev_element.remove(); | ||
} | ||
if (render_fn) { | ||
@@ -148,3 +143,3 @@ // If hydrating, use the existing ssr comment as the anchor so that the | ||
return noop; | ||
}); | ||
}, EFFECT_TRANSPARENT); | ||
} |
@@ -227,6 +227,7 @@ import { DEV } from 'esm-env'; | ||
while (current_context !== null) { | ||
/** @type {string} */ | ||
var filename = current_context.function?.filename; | ||
if (filename) { | ||
const file = filename.split('/').at(-1); | ||
const file = filename.split('/').pop(); | ||
component_stack.push(file); | ||
@@ -233,0 +234,0 @@ } |
@@ -41,3 +41,3 @@ import { | ||
var message = | ||
`${stringify(child)} cannot contain ${stringify(parent)}\n\n` + | ||
`${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.'; | ||
@@ -44,0 +44,0 @@ |
@@ -75,14 +75,18 @@ import { is_promise, noop } from '../shared/utils.js'; | ||
*/ | ||
export function element(payload, tag, attributes_fn, children_fn) { | ||
payload.out += `<${tag} `; | ||
attributes_fn(); | ||
payload.out += `>`; | ||
export function element(payload, tag, attributes_fn = noop, children_fn = noop) { | ||
if (tag) { | ||
payload.out += `<${tag} `; | ||
attributes_fn(); | ||
payload.out += `>`; | ||
if (!VoidElements.has(tag)) { | ||
children_fn(); | ||
if (!RawTextElements.includes(tag)) { | ||
payload.out += BLOCK_ANCHOR; | ||
if (!VoidElements.has(tag)) { | ||
children_fn(); | ||
if (!RawTextElements.includes(tag)) { | ||
payload.out += BLOCK_ANCHOR; | ||
} | ||
payload.out += `</${tag}>`; | ||
} | ||
payload.out += `</${tag}>`; | ||
} | ||
payload.out += '<!---->'; | ||
} | ||
@@ -89,0 +93,0 @@ |
@@ -5,1 +5,5 @@ export type Store<V> = { | ||
}; | ||
export type SourceLocation = | ||
| [line: number, column: number] | ||
| [line: number, column: number, SourceLocation[]]; |
@@ -1,2 +0,2 @@ | ||
import { is_void } from '../../compiler/phases/1-parse/utils/names.js'; | ||
import { is_void } from '../../constants.js'; | ||
import * as w from './warnings.js'; | ||
@@ -3,0 +3,0 @@ import * as e from './errors.js'; |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.0.0-next.175'; | ||
export const VERSION = '5.0.0-next.176'; | ||
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
2118040
46447