Socket
Socket
Sign inDemoInstall

svelte

Package Overview
Dependencies
18
Maintainers
3
Versions
596
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 5.0.0-next.95 to 5.0.0-next.96

src/compiler/phases/2-analyze/css/css-warn.js

2

package.json

@@ -5,3 +5,3 @@ {

"license": "MIT",
"version": "5.0.0-next.95",
"version": "5.0.0-next.96",
"type": "module",

@@ -8,0 +8,0 @@ "types": "./types/index.d.ts",

@@ -214,1 +214,22 @@ declare module '*.svelte' {

): { with: (fn: (type: 'init' | 'update', ...values: T) => void) => void };
/**
* Retrieves the `this` reference of the custom element that contains this component. Example:
*
* ```svelte
* <svelte:options customElement="my-element" />
*
* <script>
* function greet(greeting) {
* $host().dispatchEvent(new CustomEvent('greeting', { detail: greeting }))
* }
* </script>
*
* <button onclick={() => greet('hello')}>say hello</button>
* ```
*
* Only available inside custom element components, and only on the client-side.
*
* https://svelte-5-preview.vercel.app/docs/runes#$host
*/
declare function $host<El extends HTMLElement = HTMLElement>(): El;

@@ -190,2 +190,4 @@ /** @typedef {{ start?: number, end?: number }} NodeLike */

'invalid-effect-location': () => `$effect() can only be used as an expression statement`,
'invalid-host-location': () =>
`$host() can only be used inside custom element component instances`,
/**

@@ -192,0 +194,0 @@ * @param {boolean} is_binding

@@ -39,3 +39,4 @@ import { error } from '../../../errors.js';

end: content_end,
styles: parser.template.slice(content_start, content_end)
styles: parser.template.slice(content_start, content_end),
comment: null
}

@@ -42,0 +43,0 @@ };

@@ -286,21 +286,22 @@ import { extract_svelte_ignore } from '../../../utils/extract_svelte_ignore.js';

parser.eat('>', true);
if (name === 'script') {
const content = read_script(parser, start, element.attributes);
/** @type {import('#compiler').Comment | null} */
let prev_comment = null;
for (let i = current.fragment.nodes.length - 1; i >= 0; i--) {
const node = current.fragment.nodes[i];
/** @type {import('#compiler').Comment | null} */
let prev_comment = null;
for (let i = current.fragment.nodes.length - 1; i >= 0; i--) {
const node = current.fragment.nodes[i];
if (i === current.fragment.nodes.length - 1 && node.end !== start) {
break;
}
if (i === current.fragment.nodes.length - 1 && node.end !== start) {
break;
}
if (node.type === 'Comment') {
prev_comment = node;
break;
} else if (node.type !== 'Text' || node.data.trim()) {
break;
}
if (node.type === 'Comment') {
prev_comment = node;
break;
} else if (node.type !== 'Text' || node.data.trim()) {
break;
}
}
if (name === 'script') {
const content = read_script(parser, start, element.attributes);
if (prev_comment) {

@@ -322,2 +323,3 @@ // We take advantage of the fact that the root will never have leadingComments set,

const content = read_style(parser, start, element.attributes);
content.content.comment = prev_comment;

@@ -324,0 +326,0 @@ if (current.css) error(start, 'duplicate-style-element');

@@ -178,3 +178,9 @@ import { walk } from 'zimmerframe';

for (const possible_sibling of siblings.keys()) {
if (apply_selector(parent_selectors, rule, possible_sibling, stylesheet)) {
if (possible_sibling.type === 'RenderTag' || possible_sibling.type === 'SlotElement') {
// `{@render foo()}<p>foo</p>` with `:global(.x) + p` is a match
if (parent_selectors.length === 1 && parent_selectors[0].metadata.is_global) {
mark(relative_selector, element);
sibling_matched = true;
}
} else if (apply_selector(parent_selectors, rule, possible_sibling, stylesheet)) {
mark(relative_selector, element);

@@ -568,24 +574,25 @@ sibling_matched = true;

let current_node = node;
do {
if (current_node.type === 'SlotElement') {
const slot_children = current_node.fragment.nodes;
if (slot_children.length > 0) {
current_node = slot_children.slice(-1)[0]; // go to its last child first
continue;
}
while (
// @ts-expect-error TODO
!current_node.prev &&
// @ts-expect-error TODO
current_node.parent?.type === 'SlotElement'
) {
// @ts-expect-error TODO
current_node = current_node.parent;
}
// @ts-expect-error
current_node = current_node.prev;
while (current_node?.type === 'SlotElement') {
const slot_children = current_node.fragment.nodes;
if (slot_children.length > 0) {
current_node = slot_children.slice(-1)[0];
} else {
break;
}
while (
// @ts-expect-error TODO
!current_node.prev &&
// @ts-expect-error TODO
current_node.parent &&
// @ts-expect-error TODO
current_node.parent.type === 'SlotElement'
) {
// @ts-expect-error TODO
current_node = current_node.parent;
}
// @ts-expect-error
current_node = current_node.prev;
} while (current_node && current_node.type === 'SlotElement');
}
return current_node;

@@ -597,6 +604,6 @@ }

* @param {boolean} adjacent_only
* @returns {Map<import('#compiler').RegularElement, NodeExistsValue>}
* @returns {Map<import('#compiler').RegularElement | import('#compiler').SvelteElement | import('#compiler').SlotElement | import('#compiler').RenderTag, NodeExistsValue>}
*/
function get_possible_element_siblings(node, adjacent_only) {
/** @type {Map<import('#compiler').RegularElement, NodeExistsValue>} */
/** @type {Map<import('#compiler').RegularElement | import('#compiler').SvelteElement | import('#compiler').SlotElement | import('#compiler').RenderTag, NodeExistsValue>} */
const result = new Map();

@@ -624,2 +631,10 @@

}
} else if (
prev.type === 'SlotElement' ||
prev.type === 'RenderTag' ||
prev.type === 'SvelteElement'
) {
result.set(prev, NODE_PROBABLY_EXISTS);
// Special case: slots, render tags and svelte:element tags could resolve to no siblings,
// so we want to continue until we find a definite sibling even with the adjacent-only combinator
}

@@ -727,3 +742,3 @@ }

/**
* @param {Map<import('#compiler').RegularElement, NodeExistsValue>} result
* @param {Map<unknown, NodeExistsValue>} result
* @returns {boolean}

@@ -742,4 +757,5 @@ */

/**
* @param {Map<import('#compiler').RegularElement, NodeExistsValue>} from
* @param {Map<import('#compiler').RegularElement, NodeExistsValue>} to
* @template T
* @param {Map<T, NodeExistsValue>} from
* @param {Map<T, NodeExistsValue>} to
* @returns {void}

@@ -746,0 +762,0 @@ */

@@ -26,2 +26,3 @@ import is_reference from 'is-reference';

import { hash } from './utils.js';
import { warn_unused } from './css/css-warn.js';

@@ -552,2 +553,3 @@ /**

}
warn_unused(analysis.css.ast, analysis.warnings);

@@ -554,0 +556,0 @@ outer: for (const element of analysis.elements) {

@@ -899,2 +899,5 @@ import {

CallExpression(node, { state, path }) {
if (get_rune(node, state.scope) === '$host') {
error(node, 'invalid-host-location');
}
validate_call_expression(node, state.scope, path);

@@ -1067,5 +1070,13 @@ },

CallExpression(node, { state, path }) {
if (get_rune(node, state.scope) === '$bindable' && node.arguments.length > 1) {
const rune = get_rune(node, state.scope);
if (rune === '$bindable' && node.arguments.length > 1) {
error(node, 'invalid-rune-args-length', '$bindable', [0, 1]);
} else if (rune === '$host') {
if (node.arguments.length > 0) {
error(node, 'invalid-rune-args-length', '$host', [0]);
} else if (state.ast_type === 'module' || !state.analysis.custom_element) {
error(node, 'invalid-host-location');
}
}
validate_call_expression(node, state.scope, path);

@@ -1072,0 +1083,0 @@ },

@@ -402,11 +402,8 @@ import { walk } from 'zimmerframe';

if (analysis.uses_props || analysis.uses_rest_props) {
const to_remove = [b.literal('children'), b.literal('$$slots'), b.literal('$$events')];
if (analysis.custom_element) {
to_remove.push(b.literal('$$host'));
}
component_block.body.unshift(
b.const(
'$$sanitized_props',
b.call(
'$.rest_props',
b.id('$$props'),
b.array([b.literal('children'), b.literal('$$slots'), b.literal('$$events')])
)
)
b.const('$$sanitized_props', b.call('$.rest_props', b.id('$$props'), b.array(to_remove)))
);

@@ -413,0 +410,0 @@ }

@@ -383,2 +383,6 @@ import { get_rune } from '../../../scope.js';

if (rune === '$host') {
return b.id('$$props.$$host');
}
if (rune === '$effect.active') {

@@ -385,0 +389,0 @@ return b.call('$.effect_active');

@@ -43,3 +43,4 @@ import { AttributeAliases, DOMBooleanAttributes } from '../../constants.js';

'$inspect',
'$inspect().with'
'$inspect().with',
'$host'
]);

@@ -46,0 +47,0 @@

@@ -0,1 +1,3 @@

import type { Comment } from '#compiler';
export namespace Css {

@@ -15,2 +17,4 @@ export interface BaseNode {

styles: string;
/** Possible comment atop the style tag */
comment: Comment | null;
};

@@ -17,0 +21,0 @@ }

@@ -10,3 +10,4 @@ import {

const css = {
'unused-selector': () => 'Unused CSS selector'
/** @param {string} name */
'css-unused-selector': (name) => `Unused CSS selector "${name}"`
};

@@ -304,2 +305,7 @@

}
// Style nodes
if (current.type === 'StyleSheet' && current.content.comment) {
ignores.push(...current.content.comment.ignores);
}
}

@@ -306,0 +312,0 @@

@@ -83,2 +83,3 @@ import { current_component_context, flush_sync, untrack } from './internal/client/runtime.js';

* https://svelte.dev/docs/svelte#createeventdispatcher
* @deprecated Use callback props and/or the `$host()` rune instead — see https://svelte-5-preview.vercel.app/docs/deprecations#createeventdispatcher
* @template {Record<string, any>} [EventMap = any]

@@ -85,0 +86,0 @@ * @returns {import('./index.js').EventDispatcher<EventMap>}

@@ -62,2 +62,5 @@ // This should contain all the public interfaces (not all of them are actually importable, check current Svelte for which ones are).

> {
/** The custom element version of the component. Only present if compiled with the `customElement` compiler option */
static element?: typeof HTMLElement;
[prop: string]: any;

@@ -64,0 +67,0 @@ /**

@@ -5,2 +5,3 @@ /** @typedef {{ file: string, line: number, column: number }} Location */

import { untrack } from '../runtime.js';
import { get_descriptors } from '../utils.js';

@@ -95,2 +96,4 @@ /** @type {Record<string, Array<{ start: Location, end: Location, component: Function }>>} */

let add_owner_visited = new Set();
/**

@@ -102,5 +105,14 @@ *

export function add_owner(object, owner) {
untrack(() => {
add_owner_to_object(object, owner);
});
// Needed because ownership addition can invoke getters on a proxy,
// calling add_owner anew, so just keeping the set as part of
// add_owner_to_object would not be enough.
const prev = add_owner_visited;
try {
add_owner_visited = new Set(add_owner_visited);
untrack(() => {
add_owner_to_object(object, owner, add_owner_visited);
});
} finally {
add_owner_visited = prev;
}
}

@@ -111,13 +123,17 @@

* @param {Function} owner
* @param {Set<any>} visited
*/
function add_owner_to_object(object, owner) {
function add_owner_to_object(object, owner, visited) {
if (visited.has(object)) return;
visited.add(object);
if (object?.[STATE_SYMBOL]?.o && !object[STATE_SYMBOL].o.has(owner)) {
object[STATE_SYMBOL].o.add(owner);
for (const key in object) {
add_owner_to_object(object[key], owner);
}
}
// Not inside previous if-block; there could be normal objects in-between
traverse_for_owners(object, (nested) => add_owner_to_object(nested, owner, visited));
}
let strip_owner_visited = new Set();
/**

@@ -127,5 +143,13 @@ * @param {any} object

export function strip_owner(object) {
untrack(() => {
strip_owner_from_object(object);
});
// Needed because ownership stripping can invoke getters on a proxy,
// calling strip_owner anew, so just keeping the set as part of
// strip_owner_from_object would not be enough.
const prev = strip_owner_visited;
try {
untrack(() => {
strip_owner_from_object(object, strip_owner_visited);
});
} finally {
strip_owner_visited = prev;
}
}

@@ -135,10 +159,45 @@

* @param {any} object
* @param {Set<any>} visited
*/
function strip_owner_from_object(object) {
function strip_owner_from_object(object, visited) {
if (visited.has(object)) return;
visited.add(object);
if (object?.[STATE_SYMBOL]?.o) {
object[STATE_SYMBOL].o = null;
}
// Not inside previous if-block; there could be normal objects in-between
traverse_for_owners(object, (nested) => strip_owner_from_object(nested, visited));
}
/**
* @param {any} object
* @param {(obj: any) => void} cb
*/
function traverse_for_owners(object, cb) {
if (typeof object === 'object' && object !== null && !(object instanceof EventTarget)) {
for (const key in object) {
strip_owner(object[key]);
cb(object[key]);
}
// deal with state on classes
const proto = Object.getPrototypeOf(object);
if (
proto !== Object.prototype &&
proto !== Array.prototype &&
proto !== Map.prototype &&
proto !== Set.prototype &&
proto !== Date.prototype
) {
const descriptors = get_descriptors(proto);
for (let key in descriptors) {
const get = descriptors[key].get;
if (get) {
try {
cb(object[key]);
} catch (e) {
// continue
}
}
}
}
}

@@ -145,0 +204,0 @@ }

import { hydrate_anchor, hydrate_nodes, hydrating, set_hydrate_nodes } from '../hydration.js';
import { empty } from '../operations.js';
import { block } from '../../reactivity/effects.js';
import { HYDRATION_START } from '../../../../constants.js';
import { HYDRATION_END, HYDRATION_START } from '../../../../constants.js';
/**
* @type {Node | undefined}
*/
let head_anchor;
export function reset_head_anchor() {
head_anchor = undefined;
}
/**
* @param {(anchor: Node) => import('#client').Dom | void} render_fn

@@ -22,8 +31,16 @@ * @returns {void}

let anchor = /** @type {import('#client').TemplateNode} */ (document.head.firstChild);
while (anchor.nodeType !== 8 || /** @type {Comment} */ (anchor).data !== HYDRATION_START) {
anchor = /** @type {import('#client').TemplateNode} */ (anchor.nextSibling);
// 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);
}
anchor = /** @type {import('#client').TemplateNode} */ (hydrate_anchor(anchor));
while (
head_anchor.nodeType !== 8 ||
/** @type {Comment} */ (head_anchor).data !== HYDRATION_START
) {
head_anchor = /** @type {import('#client').TemplateNode} */ (head_anchor.nextSibling);
}
head_anchor = /** @type {import('#client').TemplateNode} */ (hydrate_anchor(head_anchor));
head_anchor = /** @type {import('#client').TemplateNode} */ (head_anchor.nextSibling);
} else {

@@ -30,0 +47,0 @@ anchor = document.head.appendChild(empty());

@@ -141,3 +141,4 @@ import { createClassComponent } from '../../../../legacy/legacy-client.js';

...this.$$d,
$$slots
$$slots,
$$host: this
}

@@ -144,0 +145,0 @@ });

@@ -6,2 +6,3 @@ import { hydrate_nodes, hydrating } from './hydration.js';

import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../constants.js';
import { effect } from '../reactivity/effects.js';

@@ -124,3 +125,10 @@ /**

function run_scripts(node) {
for (const script of node.querySelectorAll('script')) {
// scripts were SSR'd, in which case they will run
if (hydrating) return;
const scripts =
/** @type {HTMLElement} */ (node).tagName === 'SCRIPT'
? [/** @type {HTMLScriptElement} */ (node)]
: node.querySelectorAll('script');
for (const script of scripts) {
var clone = document.createElement('script');

@@ -132,3 +140,11 @@ for (var attribute of script.attributes) {

clone.textContent = script.textContent;
script.replaceWith(clone);
// If node === script tag, replaceWith will do nothing because there's no parent yet,
// waiting until that's the case using an effect solves this.
// Don't do it in other circumstances or we could accidentally execute scripts
// in an adjacent @html tag that was instantiated in the meantime.
if (script === node) {
effect(() => script.replaceWith(clone));
} else {
script.replaceWith(clone);
}
}

@@ -135,0 +151,0 @@ }

import { DEV } from 'esm-env';
import { get, batch_inspect, current_component_context, untrack } from './runtime.js';
import { effect_active } from './reactivity/effects.js';
import {
get,
batch_inspect,
current_component_context,
untrack,
current_effect
} from './runtime.js';
import {
array_prototype,

@@ -209,3 +214,3 @@ define_property,

s === undefined &&
(effect_active() || updating_derived) &&
(current_effect !== null || updating_derived) &&
(!(prop in target) || get_descriptor(target, prop)?.writable)

@@ -254,3 +259,6 @@ ) {

let s = metadata.s.get(prop);
if (s !== undefined || (effect_active() && (!has || get_descriptor(target, prop)?.writable))) {
if (
s !== undefined ||
(current_effect !== null && (!has || get_descriptor(target, prop)?.writable))
) {
if (s === undefined) {

@@ -278,3 +286,3 @@ s = (metadata.i ? source : mutable_source)(

// object property before writing to that property.
if (s === undefined && effect_active()) {
if (s === undefined && current_effect !== null) {
// the read creates a signal

@@ -281,0 +289,0 @@ untrack(() => receiver[prop]);

@@ -21,2 +21,3 @@ import { DEV } from 'esm-env';

import { handle_event_propagation } from './dom/elements/events.js';
import { reset_head_anchor } from './dom/blocks/svelte-head.js';

@@ -179,2 +180,3 @@ /** @type {Set<string>} */

set_hydrate_nodes(previous_hydrate_nodes);
reset_head_anchor();
}

@@ -181,0 +183,0 @@ }

@@ -210,6 +210,3 @@ import { is_promise, noop } from '../shared/utils.js';

return {
head:
payload.head.out || payload.head.title
? payload.head.title + BLOCK_OPEN + payload.head.out + BLOCK_CLOSE
: '',
head: payload.head.out || payload.head.title ? payload.head.out + payload.head.title : '',
html: payload.out

@@ -251,3 +248,5 @@ };

const head_payload = payload.head;
payload.head.out += BLOCK_OPEN;
fn(head_payload);
payload.head.out += BLOCK_CLOSE;
}

@@ -254,0 +253,0 @@

@@ -9,3 +9,3 @@ // generated during release, do not modify

*/
export const VERSION = '5.0.0-next.95';
export const VERSION = '5.0.0-next.96';
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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc