Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

svelte

Package Overview
Dependencies
Maintainers
3
Versions
820
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

svelte - npm Package Compare versions

Comparing version 5.5.2 to 5.5.3

src/internal/client/dev/assign.js

2

package.json

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

"license": "MIT",
"version": "5.5.2",
"version": "5.5.3",
"type": "module",

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

@@ -1,6 +0,12 @@

/** @import { AssignmentExpression, AssignmentOperator, Expression, Pattern } from 'estree' */
/** @import { Location } from 'locate-character' */
/** @import { AssignmentExpression, AssignmentOperator, Expression, Identifier, Literal, MemberExpression, Pattern } from 'estree' */
/** @import { AST } from '#compiler' */
/** @import { Context } from '../types.js' */
import * as b from '../../../../utils/builders.js';
import { build_assignment_value } from '../../../../utils/ast.js';
import { is_ignored } from '../../../../state.js';
import {
build_assignment_value,
get_attribute_expression,
is_event_attribute
} from '../../../../utils/ast.js';
import { dev, filename, is_ignored, locator } from '../../../../state.js';
import { build_proxy_reassignment, should_proxy } from '../utils.js';

@@ -24,3 +30,21 @@ import { visit_assignment_expression } from '../../shared/assignments.js';

/**
* Determines whether the value will be coerced on assignment (as with e.g. `+=`).
* If not, we may need to proxify the value, or warn that the value will not be
* proxified in time
* @param {AssignmentOperator} operator
*/
function is_non_coercive_operator(operator) {
return ['=', '||=', '&&=', '??='].includes(operator);
}
/** @type {Record<string, string>} */
const callees = {
'=': '$.assign',
'&&=': '$.assign_and',
'||=': '$.assign_or',
'??=': '$.assign_nullish'
};
/**
* @param {AssignmentOperator} operator
* @param {Pattern} left

@@ -45,3 +69,7 @@ * @param {Expression} right

if (private_state.kind !== 'raw_state' && should_proxy(value, context.state.scope)) {
if (
private_state.kind === 'state' &&
is_non_coercive_operator(operator) &&
should_proxy(value, context.state.scope)
) {
value = build_proxy_reassignment(value, b.member(b.this, private_state.id));

@@ -78,4 +106,10 @@ }

const path = context.path.map((node) => node.type);
// reassignment
if (object === left && transform?.assign) {
// special case — if an element binding, we know it's a primitive
const is_primitive = path.at(-1) === 'BindDirective' && path.at(-2) === 'RegularElement';
let value = /** @type {Expression} */ (

@@ -85,6 +119,2 @@ context.visit(build_assignment_value(operator, left, right))

// special case — if an element binding, we know it's a primitive
const path = context.path.map((node) => node.type);
const is_primitive = path.at(-1) === 'BindDirective' && path.at(-2) === 'RegularElement';
if (

@@ -94,6 +124,8 @@ !is_primitive &&

binding.kind !== 'bindable_prop' &&
binding.kind !== 'raw_state' &&
context.state.analysis.runes &&
should_proxy(value, context.state.scope)
should_proxy(right, context.state.scope) &&
is_non_coercive_operator(operator)
) {
value = binding.kind === 'raw_state' ? value : build_proxy_reassignment(value, object);
value = build_proxy_reassignment(value, object);
}

@@ -116,3 +148,55 @@

// in cases like `(object.items ??= []).push(value)`, we may need to warn
// if the value gets proxified, since the proxy _isn't_ the thing that
// will be pushed to. we do this by transforming it to something like
// `$.assign_nullish(object, 'items', [])`
let should_transform =
dev && path.at(-1) !== 'ExpressionStatement' && is_non_coercive_operator(operator);
// special case — ignore `onclick={() => (...)}`
if (
path.at(-1) === 'ArrowFunctionExpression' &&
(path.at(-2) === 'RegularElement' || path.at(-2) === 'SvelteElement')
) {
const element = /** @type {AST.RegularElement} */ (context.path.at(-2));
const attribute = element.attributes.find((attribute) => {
if (attribute.type !== 'Attribute' || !is_event_attribute(attribute)) {
return false;
}
const expression = get_attribute_expression(attribute);
return expression === context.path.at(-1);
});
if (attribute) {
should_transform = false;
}
}
if (left.type === 'MemberExpression' && should_transform) {
const callee = callees[operator];
const loc = /** @type {Location} */ (locator(/** @type {number} */ (left.start)));
const location = `${filename}:${loc.line}:${loc.column}`;
return /** @type {Expression} */ (
context.visit(
b.call(
callee,
/** @type {Expression} */ (left.object),
/** @type {Expression} */ (
left.computed
? left.property
: b.literal(/** @type {Identifier} */ (left.property).name)
),
right,
b.literal(location)
)
)
);
}
return null;
}

@@ -187,13 +187,18 @@ /** @import { ClassBody, Expression, Identifier, Literal, MethodDefinition, PrivateIdentifier, PropertyDefinition } from 'estree' */

[b.id('owner')],
Array.from(public_state.keys()).map((name) =>
b.stmt(
b.call(
'$.add_owner',
b.call('$.get', b.member(b.this, b.private_id(name))),
b.id('owner'),
b.literal(false),
is_ignored(node, 'ownership_invalid_binding') && b.true
Array.from(public_state)
// Only run ownership addition on $state fields.
// Theoretically someone could create a `$state` while creating `$state.raw` or inside a `$derived.by`,
// but that feels so much of an edge case that it doesn't warrant a perf hit for the common case.
.filter(([_, { kind }]) => kind === 'state')
.map(([name]) =>
b.stmt(
b.call(
'$.add_owner',
b.call('$.get', b.member(b.this, b.private_id(name))),
b.id('owner'),
b.literal(false),
is_ignored(node, 'ownership_invalid_binding') && b.true
)
)
)
),
),
true

@@ -200,0 +205,0 @@ )

@@ -5,3 +5,3 @@ /** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Property, Statement } from 'estree' */

import { dev, is_ignored } from '../../../../../state.js';
import { get_attribute_chunks } from '../../../../../utils/ast.js';
import { get_attribute_chunks, object } from '../../../../../utils/ast.js';
import * as b from '../../../../../utils/builders.js';

@@ -180,12 +180,22 @@ import { create_derived } from '../../utils.js';

if (dev) {
binding_initializers.push(
b.stmt(
b.call(
b.id('$.add_owner_effect'),
b.thunk(expression),
b.id(component_name),
is_ignored(node, 'ownership_invalid_binding') && b.true
const left = object(attribute.expression);
let binding;
if (left?.type === 'Identifier') {
binding = context.state.scope.get(left.name);
}
// Only run ownership addition on $state fields.
// Theoretically someone could create a `$state` while creating `$state.raw` or inside a `$derived.by`,
// but that feels so much of an edge case that it doesn't warrant a perf hit for the common case.
if (binding?.kind !== 'derived' && binding?.kind !== 'raw_state') {
binding_initializers.push(
b.stmt(
b.call(
b.id('$.add_owner_effect'),
b.thunk(expression),
b.id(component_name),
is_ignored(node, 'ownership_invalid_binding') && b.true
)
)
)
);
);
}
}

@@ -192,0 +202,0 @@

export { FILENAME, HMR, NAMESPACE_SVG } from '../../constants.js';
export { assign, assign_and, assign_or, assign_nullish } from './dev/assign.js';
export { cleanup_styles } from './dev/css.js';

@@ -3,0 +4,0 @@ export { add_locations } from './dev/elements.js';

@@ -51,2 +51,5 @@ /** @import { ComponentContext, Derived, Effect, Reaction, Signal, Source, Value } from '#client' */

/** @type {Effect | null} */
let last_scheduled_effect = null;
export let is_flushing_effect = false;

@@ -536,9 +539,18 @@ export let is_destroying_effect = false;

function log_effect_stack() {
// eslint-disable-next-line no-console
console.error(
'Last ten effects were: ',
dev_effect_stack.slice(-10).map((d) => d.fn)
);
dev_effect_stack = [];
}
function infinite_loop_guard() {
if (flush_count > 1000) {
flush_count = 0;
if (DEV) {
try {
e.effect_update_depth_exceeded();
} catch (error) {
try {
e.effect_update_depth_exceeded();
} catch (error) {
if (DEV) {
// stack is garbage, ignore. Instead add a console.error message.

@@ -548,12 +560,23 @@ define_property(error, 'stack', {

});
// eslint-disable-next-line no-console
console.error(
'Last ten effects were: ',
dev_effect_stack.slice(-10).map((d) => d.fn)
);
dev_effect_stack = [];
}
// Try and handle the error so it can be caught at a boundary, that's
// if there's an effect available from when it was last scheduled
if (last_scheduled_effect !== null) {
if (DEV) {
try {
handle_error(error, last_scheduled_effect, null, null);
} catch (e) {
// Only log the effect stack if the error is re-thrown
log_effect_stack();
throw e;
}
} else {
handle_error(error, last_scheduled_effect, null, null);
}
} else {
if (DEV) {
log_effect_stack();
}
throw error;
}
} else {
e.effect_update_depth_exceeded();
}

@@ -643,4 +666,6 @@ }

flush_queued_root_effects(previous_queued_root_effects);
if (!is_micro_task_queued) {
flush_count = 0;
last_scheduled_effect = null;
if (DEV) {

@@ -664,2 +689,4 @@ dev_effect_stack = [];

last_scheduled_effect = signal;
var effect = signal;

@@ -784,2 +811,3 @@

flush_count = 0;
last_scheduled_effect = null;
if (DEV) {

@@ -786,0 +814,0 @@ dev_effect_stack = [];

@@ -9,2 +9,16 @@ /* This file is generated by scripts/process-messages/index.js. Do not edit! */

/**
* Assignment to `%property%` property (%location%) will evaluate to the right-hand side, not the value of `%property%` following the assignment. This may result in unexpected behaviour.
* @param {string} property
* @param {string} location
*/
export function assignment_value_stale(property, location) {
if (DEV) {
console.warn(`%c[svelte] assignment_value_stale\n%cAssignment to \`${property}\` property (${location}) will evaluate to the right-hand side, not the value of \`${property}\` following the assignment. This may result in unexpected behaviour.`, bold, normal);
} else {
// TODO print a link to the documentation
console.warn("assignment_value_stale");
}
}
/**
* `%binding%` (%location%) is binding to a non-reactive property

@@ -11,0 +25,0 @@ * @param {string} binding

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

*/
export const VERSION = '5.5.2';
export const VERSION = '5.5.3';
export const PUBLIC_VERSION = '5';

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
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc