Comparing version 5.0.0-next.201 to 5.0.0-next.202
@@ -5,3 +5,3 @@ { | ||
"license": "MIT", | ||
"version": "5.0.0-next.201", | ||
"version": "5.0.0-next.202", | ||
"type": "module", | ||
@@ -8,0 +8,0 @@ "types": "./types/index.d.ts", |
@@ -122,9 +122,19 @@ /** @import { LegacyRoot } from './types/legacy-nodes.js' */ | ||
if (modern) { | ||
const clean = (/** @type {any} */ node) => { | ||
delete node.metadata; | ||
delete node.parent; | ||
}; | ||
ast.options?.attributes.forEach((attribute) => { | ||
clean(attribute); | ||
clean(attribute.value); | ||
if (Array.isArray(attribute.value)) { | ||
attribute.value.forEach(clean); | ||
} | ||
}); | ||
// remove things that we don't want to treat as public API | ||
return zimmerframe_walk(ast, null, { | ||
_(node, { next }) { | ||
// @ts-ignore | ||
delete node.parent; | ||
// @ts-ignore | ||
delete node.metadata; | ||
clean(node); | ||
next(); | ||
@@ -131,0 +141,0 @@ } |
@@ -12,3 +12,3 @@ /** @import { Expression } from 'estree' */ | ||
import { create_fragment } from '../utils/create.js'; | ||
import { create_attribute } from '../../nodes.js'; | ||
import { create_attribute, create_expression_metadata } from '../../nodes.js'; | ||
import { get_attribute_expression, is_expression_attribute } from '../../../utils/ast.js'; | ||
@@ -131,3 +131,3 @@ import { closing_tag_omitted } from '../../../../html-tree-validation.js'; | ||
? meta_tags.get(name) | ||
: regex_capital_letter.test(name[0]) || name === 'svelte:self' || name === 'svelte:component' | ||
: regex_capital_letter.test(name[0]) | ||
? 'Component' | ||
@@ -145,3 +145,3 @@ : name === 'title' && parent_is_head(parser.stack) | ||
? { | ||
type: type, | ||
type, | ||
start, | ||
@@ -169,3 +169,3 @@ end: -1, | ||
metadata: { | ||
svg: false | ||
// unpopulated at first, differs between types | ||
} | ||
@@ -515,4 +515,3 @@ }); | ||
metadata: { | ||
contains_call_expression: false, | ||
dynamic: false | ||
expression: create_expression_metadata() | ||
} | ||
@@ -546,4 +545,3 @@ }; | ||
metadata: { | ||
dynamic: false, | ||
contains_call_expression: false | ||
expression: create_expression_metadata() | ||
} | ||
@@ -593,3 +591,3 @@ }; | ||
metadata: { | ||
dynamic: false | ||
expression: create_expression_metadata() | ||
} | ||
@@ -626,13 +624,6 @@ }; | ||
metadata: { | ||
dynamic: false, | ||
contains_call_expression: false | ||
expression: create_expression_metadata() | ||
} | ||
}; | ||
if (directive.type === 'ClassDirective') { | ||
directive.metadata = { | ||
dynamic: false | ||
}; | ||
} | ||
if (directive.type === 'TransitionDirective') { | ||
@@ -800,4 +791,3 @@ const direction = name.slice(0, colon_index); | ||
metadata: { | ||
contains_call_expression: false, | ||
dynamic: false | ||
expression: create_expression_metadata() | ||
} | ||
@@ -804,0 +794,0 @@ }; |
@@ -10,2 +10,3 @@ /** @import { ArrowFunctionExpression, Expression, Identifier } from 'estree' */ | ||
import { parse_expression_at } from '../acorn.js'; | ||
import { create_expression_metadata } from '../../nodes.js'; | ||
@@ -43,4 +44,3 @@ const regex_whitespace_with_closing_curly_brace = /^\s*}/; | ||
metadata: { | ||
contains_call_expression: false, | ||
dynamic: false | ||
expression: create_expression_metadata() | ||
} | ||
@@ -47,0 +47,0 @@ }); |
@@ -1181,6 +1181,4 @@ /** @import { ArrowFunctionExpression, CallExpression, Expression, FunctionDeclaration, FunctionExpression, Identifier, LabeledStatement, Literal, Node, Program, Super } from 'estree' */ | ||
node.metadata.dynamic = get_attribute_chunks(node.value).some((chunk) => { | ||
if (chunk.type !== 'ExpressionTag') { | ||
return false; | ||
} | ||
for (const chunk of get_attribute_chunks(node.value)) { | ||
if (chunk.type !== 'ExpressionTag') continue; | ||
@@ -1191,7 +1189,8 @@ if ( | ||
) { | ||
return false; | ||
continue; | ||
} | ||
return chunk.metadata.dynamic || chunk.metadata.contains_call_expression; | ||
}); | ||
node.metadata.expression.has_state ||= chunk.metadata.expression.has_state; | ||
node.metadata.expression.has_call ||= chunk.metadata.expression.has_call; | ||
} | ||
@@ -1216,6 +1215,6 @@ if (is_event_attribute(node)) { | ||
ClassDirective(node, context) { | ||
context.next({ ...context.state, expression: node }); | ||
context.next({ ...context.state, expression: node.metadata.expression }); | ||
}, | ||
SpreadAttribute(node, context) { | ||
context.next({ ...context.state, expression: node }); | ||
context.next({ ...context.state, expression: node.metadata.expression }); | ||
}, | ||
@@ -1236,13 +1235,17 @@ SlotElement(node, context) { | ||
if (binding?.kind !== 'normal') { | ||
node.metadata.dynamic = true; | ||
node.metadata.expression.has_state = true; | ||
} | ||
} else { | ||
context.next(); | ||
node.metadata.dynamic = get_attribute_chunks(node.value).some( | ||
(node) => node.type === 'ExpressionTag' && node.metadata.dynamic | ||
); | ||
for (const chunk of get_attribute_chunks(node.value)) { | ||
if (chunk.type !== 'ExpressionTag') continue; | ||
node.metadata.expression.has_state ||= chunk.metadata.expression.has_state; | ||
node.metadata.expression.has_call ||= chunk.metadata.expression.has_call; | ||
} | ||
} | ||
}, | ||
ExpressionTag(node, context) { | ||
context.next({ ...context.state, expression: node }); | ||
context.next({ ...context.state, expression: node.metadata.expression }); | ||
}, | ||
@@ -1268,6 +1271,14 @@ Identifier(node, context) { | ||
if (binding && context.state.expression) { | ||
context.state.expression.dependencies.add(binding); | ||
if (binding.kind !== 'normal') { | ||
context.state.expression.has_state = true; | ||
} | ||
} | ||
// if no binding, means some global variable | ||
if (binding && binding.kind !== 'normal') { | ||
if (context.state.expression) { | ||
context.state.expression.metadata.dynamic = true; | ||
context.state.expression.has_state = true; | ||
} | ||
@@ -1305,9 +1316,6 @@ | ||
const { expression, render_tag } = context.state; | ||
if ( | ||
(expression?.type === 'ExpressionTag' || | ||
expression?.type === 'SpreadAttribute' || | ||
expression?.type === 'OnDirective') && | ||
!is_known_safe_call(node, context) | ||
) { | ||
expression.metadata.contains_call_expression = true; | ||
if (expression && !is_known_safe_call(node, context)) { | ||
expression.has_call = true; | ||
expression.has_state = true; | ||
} | ||
@@ -1363,3 +1371,3 @@ | ||
if (context.state.expression) { | ||
context.state.expression.metadata.dynamic = true; | ||
context.state.expression.has_state = true; | ||
} | ||
@@ -1378,3 +1386,3 @@ | ||
} | ||
next({ ...state, expression: node }); | ||
next({ ...state, expression: node.metadata.expression }); | ||
}, | ||
@@ -1381,0 +1389,0 @@ BindDirective(node, context) { |
@@ -5,2 +5,3 @@ import type { Scope } from '../scope.js'; | ||
ClassDirective, | ||
ExpressionMetadata, | ||
ExpressionTag, | ||
@@ -24,4 +25,4 @@ OnDirective, | ||
component_slots: Set<string>; | ||
/** The current {expression}, if any */ | ||
expression: ExpressionTag | ClassDirective | OnDirective | SpreadAttribute | null; | ||
/** Information about the current expression/directive/block value */ | ||
expression: ExpressionMetadata | null; | ||
/** The current {@render ...} tag, if any */ | ||
@@ -28,0 +29,0 @@ render_tag: null | RenderTag; |
@@ -1,2 +0,2 @@ | ||
/** @import { AssignmentExpression, CallExpression, Expression, Identifier, Node, Pattern, PrivateIdentifier, Super, UpdateExpression, VariableDeclarator } from 'estree' */ | ||
/** @import { AssignmentExpression, CallExpression, Expression, ImportDeclaration, Identifier, Node, Pattern, PrivateIdentifier, Super, UpdateExpression, VariableDeclarator } from 'estree' */ | ||
/** @import { Attribute, Component, ElementLike, Fragment, RegularElement, SvelteComponent, SvelteElement, SvelteNode, SvelteSelf, TransitionDirective } from '#compiler' */ | ||
@@ -365,2 +365,28 @@ /** @import { NodeLike } from '../../errors.js' */ | ||
const validation = { | ||
ExpressionStatement(node, { state }) { | ||
if ( | ||
node.expression.type === 'NewExpression' && | ||
node.expression.callee.type === 'Identifier' && | ||
node.expression.arguments.length === 1 && | ||
node.expression.arguments[0].type === 'ObjectExpression' && | ||
node.expression.arguments[0].properties.some( | ||
(p) => p.type === 'Property' && p.key.type === 'Identifier' && p.key.name === 'target' | ||
) | ||
) { | ||
const binding = state.scope.get(node.expression.callee.name); | ||
if (binding?.kind === 'normal' && binding.declaration_kind === 'import') { | ||
const declaration = /** @type {ImportDeclaration} */ (binding.initial); | ||
// Theoretically someone could import a class from a `.svelte.js` module, but that's too rare to worry about | ||
if ( | ||
/** @type {string} */ (declaration.source.value)?.endsWith('.svelte') && | ||
declaration.specifiers.find( | ||
(s) => s.local.name === binding.node.name && s.type === 'ImportDefaultSpecifier' | ||
) | ||
) { | ||
w.legacy_component_creation(node.expression); | ||
} | ||
} | ||
} | ||
}, | ||
MemberExpression(node, context) { | ||
@@ -367,0 +393,0 @@ if (node.object.type === 'Identifier' && node.property.type === 'Identifier') { |
@@ -15,3 +15,7 @@ /** @import { Expression, ExpressionStatement, Literal } from 'estree' */ | ||
} from '../../../../constants.js'; | ||
import { create_attribute, is_custom_element_node } from '../../../../nodes.js'; | ||
import { | ||
create_attribute, | ||
create_expression_metadata, | ||
is_custom_element_node | ||
} from '../../../../nodes.js'; | ||
import { regex_starts_with_newline } from '../../../../patterns.js'; | ||
@@ -146,4 +150,3 @@ import * as b from '../../../../../utils/builders.js'; | ||
metadata: { | ||
contains_call_expression: false, | ||
dynamic: false | ||
expression: create_expression_metadata() | ||
} | ||
@@ -163,4 +166,3 @@ } | ||
metadata: { | ||
contains_call_expression: false, | ||
dynamic: false | ||
expression: create_expression_metadata() | ||
} | ||
@@ -405,3 +407,5 @@ } | ||
), | ||
metadata: { contains_call_expression: false, dynamic: false } | ||
metadata: { | ||
expression: create_expression_metadata() | ||
} | ||
}); | ||
@@ -408,0 +412,0 @@ |
@@ -48,3 +48,3 @@ /** @import * as Compiler from '#compiler' */ | ||
metadata: { | ||
dynamic: false, | ||
expression: create_expression_metadata(), | ||
delegated: null | ||
@@ -54,1 +54,12 @@ } | ||
} | ||
/** | ||
* @returns {Compiler.ExpressionMetadata} | ||
*/ | ||
export function create_expression_metadata() { | ||
return { | ||
dependencies: new Set(), | ||
has_state: false, | ||
has_call: false | ||
}; | ||
} |
@@ -319,2 +319,11 @@ import type { | ||
export interface ExpressionMetadata { | ||
/** All the bindings that are referenced inside this expression */ | ||
dependencies: Set<Binding>; | ||
/** True if the expression references state directly, or _might_ (via member/call expressions) */ | ||
has_state: boolean; | ||
/** True if the expression involves a call expression (often, it will need to be wrapped in a derived) */ | ||
has_call: boolean; | ||
} | ||
export * from './template.js'; | ||
@@ -321,0 +330,0 @@ export { Css }; |
@@ -1,2 +0,2 @@ | ||
import type { Binding, Css } from '#compiler'; | ||
import type { Binding, Css, ExpressionMetadata } from '#compiler'; | ||
import type { | ||
@@ -114,8 +114,3 @@ ArrayExpression, | ||
metadata: { | ||
contains_call_expression: boolean; | ||
/** | ||
* Whether or not the expression contains any dynamic references — | ||
* determines whether it will be updated in a render effect or not | ||
*/ | ||
dynamic: boolean; | ||
expression: ExpressionMetadata; | ||
}; | ||
@@ -194,3 +189,3 @@ } | ||
metadata: { | ||
dynamic: false; | ||
expression: ExpressionMetadata; | ||
}; | ||
@@ -217,4 +212,3 @@ } | ||
metadata: { | ||
contains_call_expression: boolean; | ||
dynamic: boolean; | ||
expression: ExpressionMetadata; | ||
}; | ||
@@ -239,3 +233,3 @@ } | ||
metadata: { | ||
dynamic: boolean; | ||
expression: ExpressionMetadata; | ||
}; | ||
@@ -461,3 +455,3 @@ } | ||
metadata: { | ||
dynamic: boolean; | ||
expression: ExpressionMetadata; | ||
/** May be set if this is an event attribute */ | ||
@@ -472,4 +466,3 @@ delegated: null | DelegatedEvent; | ||
metadata: { | ||
contains_call_expression: boolean; | ||
dynamic: boolean; | ||
expression: ExpressionMetadata; | ||
}; | ||
@@ -476,0 +469,0 @@ } |
@@ -99,2 +99,3 @@ /* This file is generated by scripts/process-messages/index.js. Do not edit! */ | ||
"export_let_unused", | ||
"legacy_component_creation", | ||
"non_reactive_update", | ||
@@ -591,2 +592,10 @@ "perf_avoid_inline_class", | ||
/** | ||
* Svelte 5 components are no longer classes. Instantiate them using `mount` or `hydrate` (imported from 'svelte') instead. | ||
* @param {null | NodeLike} node | ||
*/ | ||
export function legacy_component_creation(node) { | ||
w(node, "legacy_component_creation", "Svelte 5 components are no longer classes. Instantiate them using `mount` or `hydrate` (imported from 'svelte') instead."); | ||
} | ||
/** | ||
* `%name%` is updated, but is not declared with `$state(...)`. Changing its value will not correctly trigger updates | ||
@@ -593,0 +602,0 @@ * @param {null | NodeLike} node |
@@ -142,3 +142,3 @@ /** @import { Effect, Source, TemplateNode } from '#client' */ | ||
// the promise might have resolved by the next microtask. | ||
Promise.resolve().then(() => { | ||
queue_micro_task(() => { | ||
if (!resolved) update(PENDING, true); | ||
@@ -145,0 +145,0 @@ }); |
@@ -344,5 +344,6 @@ import { DEV } from 'esm-env'; | ||
* accepts numeric values, but the attribute can also be set to a string like `50%`. | ||
* If this list becomes too big, rethink this approach. | ||
* In case of draggable trying to set `element.draggable='false'` will actually set | ||
* draggable to `true`. If this list becomes too big, rethink this approach. | ||
*/ | ||
var always_set_through_set_attribute = ['width', 'height']; | ||
var always_set_through_set_attribute = ['width', 'height', 'draggable']; | ||
@@ -349,0 +350,0 @@ /** @type {Map<string, string[]>} */ |
@@ -9,3 +9,3 @@ // generated during release, do not modify | ||
*/ | ||
export const VERSION = '5.0.0-next.201'; | ||
export const VERSION = '5.0.0-next.202'; | ||
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
2172889
48018
25