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

@vaadin/component-base

Package Overview
Dependencies
Maintainers
12
Versions
407
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vaadin/component-base - npm Package Compare versions

Comparing version 24.4.0-dev.223e39f050 to 24.4.0-dev.4b20a0c55

4

package.json
{
"name": "@vaadin/component-base",
"version": "24.4.0-dev.223e39f050",
"version": "24.4.0-dev.4b20a0c55",
"publishConfig": {

@@ -45,3 +45,3 @@ "access": "public"

},
"gitHead": "5e2e3bfc811c95aed9354235fab93fdbf43eb354"
"gitHead": "b79c81e5f6fd24684b34ee0dc434e94d943ea13e"
}
/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -143,4 +143,3 @@ */

*
* @type {number}
* @private
* @return {number}
*/

@@ -154,4 +153,3 @@ get size() {

*
* @type {number}
* @private
* @param {number} size
*/

@@ -158,0 +156,0 @@ set size(size) {

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -69,9 +69,2 @@ */

/**
* Indicates whether any data has been loaded since the last cache clear.
*
* @type {boolean}
*/
hasData = false;
/**
* A placeholder item that is used to indicate that the item is not loaded yet.

@@ -153,3 +146,2 @@ *

this.rootCache = this.__createRootCache(this.rootCache.size);
this.hasData = false;
}

@@ -273,4 +265,2 @@

this.hasData = true;
this.dispatchEvent(new CustomEvent('page-received'));

@@ -277,0 +267,0 @@

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -12,3 +12,3 @@ */

get() {
return '24.4.0-alpha1';
return '24.4.0-alpha17';
},

@@ -15,0 +15,0 @@ });

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -96,2 +96,5 @@ */

// Set the key for this property
this.getOrCreateMap('__propKeys').set(name, key);
if (options.sync) {

@@ -236,2 +239,22 @@ result = {

/**
* Set several properties at once and perform synchronous update.
* @protected
*/
setProperties(props) {
Object.entries(props).forEach(([name, value]) => {
// Use private key and not setter to not trigger
// update for properties marked as `sync: true`.
const key = this.constructor.__propKeys.get(name);
const oldValue = this[key];
this[key] = value;
this.requestUpdate(name, oldValue);
});
// Perform sync update
if (this.hasUpdated) {
this.performUpdate();
}
}
/** @protected */

@@ -238,0 +261,0 @@ _createMethodObserver(observer) {

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2022 - 2023 Vaadin Ltd.
* Copyright (c) 2022 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2022 - 2023 Vaadin Ltd.
* Copyright (c) 2022 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2022 - 2023 Vaadin Ltd.
* Copyright (c) 2022 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2022 - 2023 Vaadin Ltd.
* Copyright (c) 2022 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -5,0 +5,0 @@ */

/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -8,5 +8,9 @@ */

/**
* Check if two paths can be resolved as URLs
* with the same origin and pathname.
* Checks if two paths match based on their origin, pathname, and query parameters.
*
* The function matches an actual URL against an expected URL to see if they share
* the same base origin (like https://example.com), the same path (like /path/to/page),
* and if the actual URL contains at least all the query parameters with the same values
* from the expected URL.
*/
export declare function matchPaths(path1: string, path2: string): boolean;
export declare function matchPaths(actual: string, expected: string): boolean;
/**
* @license
* Copyright (c) 2023 Vaadin Ltd.
* Copyright (c) 2023 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -8,13 +8,35 @@ */

/**
* Check if two paths can be resolved as URLs
* with the same origin and pathname.
* Checks if one set of URL parameters contains all the parameters
* with the same values from another set.
*
* @param {string} path1
* @param {string} path2
* @param {URLSearchParams} actual
* @param {URLSearchParams} expected
*/
export function matchPaths(path1, path2) {
function containsQueryParams(actual, expected) {
return [...expected.entries()].every(([key, value]) => {
return actual.getAll(key).includes(value);
});
}
/**
* Checks if two paths match based on their origin, pathname, and query parameters.
*
* The function matches an actual URL against an expected URL to see if they share
* the same base origin (like https://example.com), the same path (like /path/to/page),
* and if the actual URL contains at least all the query parameters with the same values
* from the expected URL.
*
* @param {string} actual The actual URL to match.
* @param {string} expected The expected URL to match.
*/
export function matchPaths(actual, expected) {
const base = document.baseURI;
const url1 = new URL(path1, base);
const url2 = new URL(path2, base);
return url1.origin === url2.origin && url1.pathname === url2.pathname;
const actualUrl = new URL(actual, base);
const expectedUrl = new URL(expected, base);
return (
actualUrl.origin === expectedUrl.origin &&
actualUrl.pathname === expectedUrl.pathname &&
containsQueryParams(actualUrl.searchParams, expectedUrl.searchParams)
);
}
/**
* @license
* Copyright (c) 2021 - 2023 Vaadin Ltd.
* Copyright (c) 2021 - 2024 Vaadin Ltd.
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/

@@ -58,2 +58,9 @@ */

this.scrollTarget.addEventListener('virtualizer-element-focused', (e) => this.__onElementFocused(e));
this.elementsContainer.addEventListener('focusin', (e) => {
this.scrollTarget.dispatchEvent(
new CustomEvent('virtualizer-element-focused', { detail: { element: this.__getFocusedElement() } }),
);
});
if (this.reorderElements) {

@@ -86,2 +93,6 @@ // Reordering the physical elements cancels the user's grab of the scroll bar handle on Safari.

get _maxVirtualIndexOffset() {
return this.size - this._virtualCount;
}
__hasPlaceholders() {

@@ -111,3 +122,3 @@ return this.__getVisibleElements().some((el) => el.__virtualizerPlaceholder);

targetVirtualIndex = this._virtualCount - (this.size - index);
this._vidxOffset = this.size - this._virtualCount;
this._vidxOffset = this._maxVirtualIndexOffset;
} else if (targetVirtualIndex < visibleElementCount) {

@@ -142,3 +153,2 @@ if (index < OFFSET_ADJUST_MIN_THRESHOLD) {

flush() {
const startPhysicalCount = this._physicalCount;
// The scroll target is hidden.

@@ -161,7 +171,2 @@ if (this.scrollTarget.offsetHeight === 0) {

}
if (this._physicalCount !== startPhysicalCount) {
// Flushing again until physical count stabilizes fixes https://github.com/vaadin/flow-components/issues/5595#issuecomment-1770278913
this.flush();
}
}

@@ -235,2 +240,3 @@

el.style.paddingTop = '';
el.style.opacity = '';
el.__virtualizerPlaceholder = false;

@@ -260,2 +266,3 @@ }

el.style.paddingTop = `${this.__placeholderHeight}px`;
el.style.opacity = '0';
el.__virtualizerPlaceholder = true;

@@ -307,20 +314,37 @@

// Prevent element update while the scroll position is being restored
this.__preventElementUpdates = true;
// Record the scroll position before changing the size
let fvi; // First visible index
let fviOffsetBefore; // Scroll offset of the first visible index
if (size > 0) {
fvi = this.adjustedFirstVisibleIndex;
fviOffsetBefore = this.__getIndexScrollOffset(fvi);
}
// Change the size
this.__size = size;
if (!this._physicalItems) {
// Not initialized yet
this._itemsChanged({
path: 'items',
});
this.__preventElementUpdates = true;
flush();
this.__preventElementUpdates = false;
} else {
// Already initialized, just update _virtualCount
this._updateScrollerSize();
this._virtualCount = this.items.length;
this._render();
this._itemsChanged({
path: 'items',
});
flush();
// Try to restore the scroll position if the new size is larger than 0
if (size > 0) {
fvi = Math.min(fvi, size - 1);
// Note, calling scrollToIndex also updates the virtual index offset,
// causing the virtualizer to add more items when size is increased,
// and remove exceeding items when size is decreased.
this.scrollToIndex(fvi);
const fviOffsetAfter = this.__getIndexScrollOffset(fvi);
if (fviOffsetBefore !== undefined && fviOffsetAfter !== undefined) {
this._scrollTop += fviOffsetBefore - fviOffsetAfter;
}
}
this.__preventElementUpdates = false;
// When reducing size while invisible, iron-list does not update items, so

@@ -337,4 +361,3 @@ // their hidden state is not updated and their __lastUpdatedIndex is not

// Schedule and flush a resize handler. This will cause a
// re-render for the elements.
// Schedule and flush a resize handler
this._resizeHandler();

@@ -437,2 +460,71 @@ flush();

/** @private */
__getFocusedElement(visibleElements = this.__getVisibleElements()) {
return visibleElements.find(
(element) =>
element.contains(this.elementsContainer.getRootNode().activeElement) ||
element.contains(this.scrollTarget.getRootNode().activeElement),
);
}
/** @private */
__nextFocusableSiblingMissing(focusedElement, visibleElements) {
return (
// Check if focused element is the last visible DOM element
visibleElements.indexOf(focusedElement) === visibleElements.length - 1 &&
// ...while there are more items available
this.size > focusedElement.__virtualIndex + 1
);
}
/** @private */
__previousFocusableSiblingMissing(focusedElement, visibleElements) {
return (
// Check if focused element is the first visible DOM element
visibleElements.indexOf(focusedElement) === 0 &&
// ...while there are preceding items available
focusedElement.__virtualIndex > 0
);
}
/** @private */
__onElementFocused(e) {
if (!this.reorderElements) {
return;
}
const focusedElement = e.detail.element;
if (!focusedElement) {
return;
}
// User has tabbed to or within a virtualizer element.
// Check if a next or previous focusable sibling is missing while it should be there (so the user can continue tabbing).
// The focusable sibling might be missing due to the elements not yet being in the correct DOM order.
// First try flushing (which also flushes any active __scrollReorderDebouncer).
const visibleElements = this.__getVisibleElements();
if (
this.__previousFocusableSiblingMissing(focusedElement, visibleElements) ||
this.__nextFocusableSiblingMissing(focusedElement, visibleElements)
) {
this.flush();
}
// If the focusable sibling is still missing (because the focused element is at the edge of the viewport and
// the virtual scrolling logic hasn't had the need to recycle elements), scroll the virtualizer just enough to
// have the focusable sibling inside the visible viewport to force the virtualizer to recycle.
const reorderedVisibleElements = this.__getVisibleElements();
if (this.__nextFocusableSiblingMissing(focusedElement, reorderedVisibleElements)) {
this._scrollTop +=
Math.ceil(focusedElement.getBoundingClientRect().bottom) -
Math.floor(this.scrollTarget.getBoundingClientRect().bottom - 1);
this.flush();
} else if (this.__previousFocusableSiblingMissing(focusedElement, reorderedVisibleElements)) {
this._scrollTop -=
Math.ceil(this.scrollTarget.getBoundingClientRect().top + 1) -
Math.floor(focusedElement.getBoundingClientRect().top);
this.flush();
}
}
_scrollHandler() {

@@ -675,9 +767,3 @@ // The scroll target is hidden.

const visibleElements = this.__getVisibleElements();
const elementWithFocus = visibleElements.find(
(element) =>
element.contains(this.elementsContainer.getRootNode().activeElement) ||
element.contains(this.scrollTarget.getRootNode().activeElement),
);
const targetElement = elementWithFocus || visibleElements[0];
const targetElement = this.__getFocusedElement(visibleElements) || visibleElements[0];
if (!targetElement) {

@@ -717,2 +803,4 @@ // All elements are hidden, don't reorder

_adjustVirtualIndexOffset(delta) {
const maxOffset = this._maxVirtualIndexOffset;
if (this._virtualCount >= this.size) {

@@ -725,4 +813,3 @@ this._vidxOffset = 0;

const scale = this._scrollTop / (this.scrollTarget.scrollHeight - this.scrollTarget.offsetHeight);
const offset = scale * this.size;
this._vidxOffset = Math.round(offset - scale * this._virtualCount);
this._vidxOffset = Math.round(scale * maxOffset);
} else {

@@ -746,3 +833,2 @@ // Make sure user can always swipe/wheel scroll to the start and end

// Near end
const maxOffset = this.size - this._virtualCount;
if (this._scrollTop >= this._maxScrollTop && this._maxScrollTop > 0) {

@@ -749,0 +835,0 @@ this._vidxOffset = maxOffset;

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