diff options
| author | pack <pack@packgekko.xyz> | 2026-08-09 10:37:07 +0000 |
|---|---|---|
| committer | pack <pack@packgekko.xyz> | 2026-08-09 10:37:07 +0000 |
| commit | 55a4f1fc869e41aca748c63d3018f0448b1606e0 (patch) | |
| tree | d132d1d01772b6d53faee3e63c534dea5706b78a /node_modules/side-channel-list | |
| download | crud-55a4f1fc869e41aca748c63d3018f0448b1606e0.tar.gz | |
first commit
Diffstat (limited to '')
| -rw-r--r-- | node_modules/side-channel-list/.editorconfig | 9 | ||||
| -rw-r--r-- | node_modules/side-channel-list/.eslintrc | 11 | ||||
| -rw-r--r-- | node_modules/side-channel-list/.github/FUNDING.yml | 12 | ||||
| -rw-r--r-- | node_modules/side-channel-list/.nycrc | 13 | ||||
| -rw-r--r-- | node_modules/side-channel-list/CHANGELOG.md | 36 | ||||
| -rw-r--r-- | node_modules/side-channel-list/LICENSE | 21 | ||||
| -rw-r--r-- | node_modules/side-channel-list/README.md | 62 | ||||
| -rw-r--r-- | node_modules/side-channel-list/index.d.ts | 13 | ||||
| -rw-r--r-- | node_modules/side-channel-list/index.js | 111 | ||||
| -rw-r--r-- | node_modules/side-channel-list/list.d.ts | 14 | ||||
| -rw-r--r-- | node_modules/side-channel-list/package.json | 77 | ||||
| -rw-r--r-- | node_modules/side-channel-list/test/index.js | 154 | ||||
| -rw-r--r-- | node_modules/side-channel-list/tsconfig.json | 9 |
13 files changed, 542 insertions, 0 deletions
diff --git a/node_modules/side-channel-list/.editorconfig b/node_modules/side-channel-list/.editorconfig new file mode 100644 index 0000000..72e0eba --- /dev/null +++ b/node_modules/side-channel-list/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +indent_style = tab +indent_size = 2 +trim_trailing_whitespace = true diff --git a/node_modules/side-channel-list/.eslintrc b/node_modules/side-channel-list/.eslintrc new file mode 100644 index 0000000..93978e7 --- /dev/null +++ b/node_modules/side-channel-list/.eslintrc @@ -0,0 +1,11 @@ +{ + "root": true, + + "extends": "@ljharb", + + "rules": { + "max-lines-per-function": 0, + "multiline-comment-style": 1, + "new-cap": [2, { "capIsNewExceptions": ["GetIntrinsic"] }], + }, +} diff --git a/node_modules/side-channel-list/.github/FUNDING.yml b/node_modules/side-channel-list/.github/FUNDING.yml new file mode 100644 index 0000000..eaff735 --- /dev/null +++ b/node_modules/side-channel-list/.github/FUNDING.yml @@ -0,0 +1,12 @@ +# These are supported funding model platforms + +github: [ljharb] +patreon: # Replace with a single Patreon username +open_collective: # Replace with a single Open Collective username +ko_fi: # Replace with a single Ko-fi username +tidelift: npm/side-channel-list +community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry +liberapay: # Replace with a single Liberapay username +issuehunt: # Replace with a single IssueHunt username +otechie: # Replace with a single Otechie username +custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] diff --git a/node_modules/side-channel-list/.nycrc b/node_modules/side-channel-list/.nycrc new file mode 100644 index 0000000..1826526 --- /dev/null +++ b/node_modules/side-channel-list/.nycrc @@ -0,0 +1,13 @@ +{ + "all": true, + "check-coverage": false, + "reporter": ["text-summary", "text", "html", "json"], + "lines": 86, + "statements": 85.93, + "functions": 82.43, + "branches": 76.06, + "exclude": [ + "coverage", + "test" + ] +} diff --git a/node_modules/side-channel-list/CHANGELOG.md b/node_modules/side-channel-list/CHANGELOG.md new file mode 100644 index 0000000..e68bcb9 --- /dev/null +++ b/node_modules/side-channel-list/CHANGELOG.md @@ -0,0 +1,36 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [v1.0.1](https://github.com/ljharb/side-channel-list.git +/compare/v1.0.0...v1.0.1) - 2026-04-08 + +### Fixed + +- [Fix] `delete`: do not reset the list when deleting the head node of a multi-node list [`#3`](https://github.com/ljharb/side-channel-list.git +/issues/3) + +### Commits + +- [actions] update workflows [`9e79e6b`](https://github.com/ljharb/side-channel-list.git +/commit/9e79e6bf845532fafbf03b547429fe4f737214a3) +- [Deps] update `@arethetypeswrong/cli`, `@ljharb/eslint-config`, `@ljharb/tsconfig`, `@types/tape`, `eslint`, `npmignore` [`babf3ca`](https://github.com/ljharb/side-channel-list.git +/commit/babf3ca4849d2fd893a470a6b82c62a80ccc9307) +- [Deps] update `object-inspect` [`9f0f4b8`](https://github.com/ljharb/side-channel-list.git +/commit/9f0f4b88ff2aa8b7b7c9e589ac1513f133d64b9f) + +## v1.0.0 - 2024-12-10 + +### Commits + +- Initial implementation, tests, readme, types [`5d6baee`](https://github.com/ljharb/side-channel-list.git +/commit/5d6baee5c9054a1238007f5a1dfc109a7a816251) +- Initial commit [`3ae784c`](https://github.com/ljharb/side-channel-list.git +/commit/3ae784c63a47895fbaeed2a91ab54a8029a7a100) +- npm init [`07055a4`](https://github.com/ljharb/side-channel-list.git +/commit/07055a4d139895565b199dba5fe2479c1a1b9e28) +- Only apps should have lockfiles [`9573058`](https://github.com/ljharb/side-channel-list.git +/commit/9573058a47494e2d68f8c6c77b5d7fbe441949c1) diff --git a/node_modules/side-channel-list/LICENSE b/node_modules/side-channel-list/LICENSE new file mode 100644 index 0000000..f82f389 --- /dev/null +++ b/node_modules/side-channel-list/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Jordan Harband + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/node_modules/side-channel-list/README.md b/node_modules/side-channel-list/README.md new file mode 100644 index 0000000..d9c7a13 --- /dev/null +++ b/node_modules/side-channel-list/README.md @@ -0,0 +1,62 @@ +# side-channel-list <sup>[![Version Badge][npm-version-svg]][package-url]</sup> + +[![github actions][actions-image]][actions-url] +[![coverage][codecov-image]][codecov-url] +[![License][license-image]][license-url] +[![Downloads][downloads-image]][downloads-url] + +[![npm badge][npm-badge-png]][package-url] + +Store information about any JS value in a side channel, using a linked list. + +Warning: this implementation will leak memory until you `delete` the `key`. +Use [`side-channel`](https://npmjs.com/side-channel) for the best available strategy. + +## Getting started + +```sh +npm install --save side-channel-list +``` + +## Usage/Examples + +```js +const assert = require('assert'); +const getSideChannelList = require('side-channel-list'); + +const channel = getSideChannelList(); + +const key = {}; +assert.equal(channel.has(key), false); +assert.throws(() => channel.assert(key), TypeError); + +channel.set(key, 42); + +channel.assert(key); // does not throw +assert.equal(channel.has(key), true); +assert.equal(channel.get(key), 42); + +channel.delete(key); +assert.equal(channel.has(key), false); +assert.throws(() => channel.assert(key), TypeError); +``` + +## Tests + +Clone the repo, `npm install`, and run `npm test` + +[package-url]: https://npmjs.org/package/side-channel-list +[npm-version-svg]: https://versionbadg.es/ljharb/side-channel-list.svg +[deps-svg]: https://david-dm.org/ljharb/side-channel-list.svg +[deps-url]: https://david-dm.org/ljharb/side-channel-list +[dev-deps-svg]: https://david-dm.org/ljharb/side-channel-list/dev-status.svg +[dev-deps-url]: https://david-dm.org/ljharb/side-channel-list#info=devDependencies +[npm-badge-png]: https://nodei.co/npm/side-channel-list.png?downloads=true&stars=true +[license-image]: https://img.shields.io/npm/l/side-channel-list.svg +[license-url]: LICENSE +[downloads-image]: https://img.shields.io/npm/dm/side-channel-list.svg +[downloads-url]: https://npm-stat.com/charts.html?package=side-channel-list +[codecov-image]: https://codecov.io/gh/ljharb/side-channel-list/branch/main/graphs/badge.svg +[codecov-url]: https://app.codecov.io/gh/ljharb/side-channel-list/ +[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/side-channel-list +[actions-url]: https://github.com/ljharb/side-channel-list/actions diff --git a/node_modules/side-channel-list/index.d.ts b/node_modules/side-channel-list/index.d.ts new file mode 100644 index 0000000..c9cabc8 --- /dev/null +++ b/node_modules/side-channel-list/index.d.ts @@ -0,0 +1,13 @@ +declare namespace getSideChannelList { + type Channel<K, V> = { + assert: (key: K) => void; + has: (key: K) => boolean; + get: (key: K) => V | undefined; + set: (key: K, value: V) => void; + delete: (key: K) => boolean; + }; +} + +declare function getSideChannelList<V, K>(): getSideChannelList.Channel<K, V>; + +export = getSideChannelList; diff --git a/node_modules/side-channel-list/index.js b/node_modules/side-channel-list/index.js new file mode 100644 index 0000000..4460229 --- /dev/null +++ b/node_modules/side-channel-list/index.js @@ -0,0 +1,111 @@ +'use strict'; + +var inspect = require('object-inspect'); + +var $TypeError = require('es-errors/type'); + +/* +* This function traverses the list returning the node corresponding to the given key. +* +* That node is also moved to the head of the list, so that if it's accessed again we don't need to traverse the whole list. +* By doing so, all the recently used nodes can be accessed relatively quickly. +*/ +/** @type {import('./list.d.ts').listGetNode} */ +// eslint-disable-next-line consistent-return +var listGetNode = function (list, key, isDelete) { + /** @type {typeof list | NonNullable<(typeof list)['next']>} */ + var prev = list; + /** @type {(typeof list)['next']} */ + var curr; + // eslint-disable-next-line eqeqeq + for (; (curr = prev.next) != null; prev = curr) { + if (curr.key === key) { + prev.next = curr.next; + if (!isDelete) { + // eslint-disable-next-line no-extra-parens + curr.next = /** @type {NonNullable<typeof list.next>} */ (list.next); + list.next = curr; // eslint-disable-line no-param-reassign + } + return curr; + } + } +}; + +/** @type {import('./list.d.ts').listGet} */ +var listGet = function (objects, key) { + if (!objects) { + return void undefined; + } + var node = listGetNode(objects, key); + return node && node.value; +}; +/** @type {import('./list.d.ts').listSet} */ +var listSet = function (objects, key, value) { + var node = listGetNode(objects, key); + if (node) { + node.value = value; + } else { + // Prepend the new node to the beginning of the list + objects.next = /** @type {import('./list.d.ts').ListNode<typeof value, typeof key>} */ ({ // eslint-disable-line no-param-reassign, no-extra-parens + key: key, + next: objects.next, + value: value + }); + } +}; +/** @type {import('./list.d.ts').listHas} */ +var listHas = function (objects, key) { + if (!objects) { + return false; + } + return !!listGetNode(objects, key); +}; +/** @type {import('./list.d.ts').listDelete} */ +// eslint-disable-next-line consistent-return +var listDelete = function (objects, key) { + if (objects) { + return listGetNode(objects, key, true); + } +}; + +/** @type {import('.')} */ +module.exports = function getSideChannelList() { + /** @typedef {ReturnType<typeof getSideChannelList>} Channel */ + /** @typedef {Parameters<Channel['get']>[0]} K */ + /** @typedef {Parameters<Channel['set']>[1]} V */ + + /** @type {import('./list.d.ts').RootNode<V, K> | undefined} */ var $o; + + /** @type {Channel} */ + var channel = { + assert: function (key) { + if (!channel.has(key)) { + throw new $TypeError('Side channel does not contain ' + inspect(key)); + } + }, + 'delete': function (key) { + var deletedNode = listDelete($o, key); + if (deletedNode && $o && !$o.next) { + $o = void undefined; + } + return !!deletedNode; + }, + get: function (key) { + return listGet($o, key); + }, + has: function (key) { + return listHas($o, key); + }, + set: function (key, value) { + if (!$o) { + // Initialize the linked list as an empty node, so that we don't have to special-case handling of the first node: we can always refer to it as (previous node).next, instead of something like (list).head + $o = { + next: void undefined + }; + } + // eslint-disable-next-line no-extra-parens + listSet(/** @type {NonNullable<typeof $o>} */ ($o), key, value); + } + }; + return channel; +}; diff --git a/node_modules/side-channel-list/list.d.ts b/node_modules/side-channel-list/list.d.ts new file mode 100644 index 0000000..2c759e2 --- /dev/null +++ b/node_modules/side-channel-list/list.d.ts @@ -0,0 +1,14 @@ +type ListNode<T, K> = { + key: K; + next: undefined | ListNode<T, K>; + value: T; +}; +type RootNode<T, K> = { + next: undefined | ListNode<T, K>; +}; + +export function listGetNode<T, K>(list: RootNode<T, K>, key: ListNode<T, K>['key'], isDelete?: boolean): ListNode<T, K> | undefined; +export function listGet<T, K>(objects: undefined | RootNode<T, K>, key: ListNode<T, K>['key']): T | undefined; +export function listSet<T, K>(objects: RootNode<T, K>, key: ListNode<T, K>['key'], value: T): void; +export function listHas<T, K>(objects: undefined | RootNode<T, K>, key: ListNode<T, K>['key']): boolean; +export function listDelete<T, K>(objects: undefined | RootNode<T, K>, key: ListNode<T, K>['key']): ListNode<T, K> | undefined; diff --git a/node_modules/side-channel-list/package.json b/node_modules/side-channel-list/package.json new file mode 100644 index 0000000..bc4c08c --- /dev/null +++ b/node_modules/side-channel-list/package.json @@ -0,0 +1,77 @@ +{ + "name": "side-channel-list", + "version": "1.0.1", + "description": "Store information about any JS value in a side channel, using a linked list", + "main": "index.js", + "exports": { + ".": "./index.js", + "./package.json": "./package.json" + }, + "types": "./index.d.ts", + "scripts": { + "prepack": "npmignore --auto --commentLines=autogenerated", + "prepublishOnly": "safe-publish-latest", + "prepublish": "not-in-publish || npm run prepublishOnly", + "prelint": "evalmd README.md && eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')", + "lint": "eslint --ext=js,mjs .", + "postlint": "tsc -p . && attw -P", + "pretest": "npm run lint", + "tests-only": "nyc tape 'test/**/*.js'", + "test": "npm run tests-only", + "posttest": "npx npm@'>= 10.2' audit --production", + "version": "auto-changelog && git add CHANGELOG.md", + "postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\"" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/ljharb/side-channel-list.git" + }, + "keywords": [], + "author": "Jordan Harband <ljharb@gmail.com>", + "funding": { + "url": "https://github.com/sponsors/ljharb" + }, + "license": "MIT", + "bugs": { + "url": "https://github.com/ljharb/side-channel-list/issues" + }, + "homepage": "https://github.com/ljharb/side-channel-list#readme", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.18.2", + "@ljharb/eslint-config": "^22.2.2", + "@ljharb/tsconfig": "^0.3.2", + "@types/object-inspect": "^1.13.0", + "@types/tape": "^5.8.1", + "auto-changelog": "^2.5.0", + "eclint": "^2.8.1", + "encoding": "^0.1.13", + "eslint": "^8.57.1", + "evalmd": "^0.0.19", + "in-publish": "^2.0.1", + "npmignore": "^0.3.5", + "nyc": "^10.3.2", + "safe-publish-latest": "^2.0.0", + "tape": "^5.9.0", + "typescript": "next" + }, + "auto-changelog": { + "output": "CHANGELOG.md", + "template": "keepachangelog", + "unreleased": false, + "commitLimit": false, + "backfillLimit": false, + "hideCredit": true + }, + "publishConfig": { + "ignore": [ + ".github/workflows" + ] + }, + "engines": { + "node": ">= 0.4" + } +} diff --git a/node_modules/side-channel-list/test/index.js b/node_modules/side-channel-list/test/index.js new file mode 100644 index 0000000..d1b915d --- /dev/null +++ b/node_modules/side-channel-list/test/index.js @@ -0,0 +1,154 @@ +'use strict'; + +var test = require('tape'); + +var getSideChannelList = require('../'); + +test('getSideChannelList', function (t) { + t.test('export', function (st) { + st.equal(typeof getSideChannelList, 'function', 'is a function'); + + st.equal(getSideChannelList.length, 0, 'takes no arguments'); + + var channel = getSideChannelList(); + st.ok(channel, 'is truthy'); + st.equal(typeof channel, 'object', 'is an object'); + st.end(); + }); + + t.test('assert', function (st) { + var channel = getSideChannelList(); + st['throws']( + function () { channel.assert({}); }, + TypeError, + 'nonexistent value throws' + ); + + var o = {}; + channel.set(o, 'data'); + st.doesNotThrow(function () { channel.assert(o); }, 'existent value noops'); + + st.end(); + }); + + t.test('has', function (st) { + var channel = getSideChannelList(); + /** @type {unknown[]} */ var o = []; + + st.equal(channel.has(o), false, 'nonexistent value yields false'); + + channel.set(o, 'foo'); + st.equal(channel.has(o), true, 'existent value yields true'); + + st.equal(channel.has('abc'), false, 'non object value non existent yields false'); + + channel.set('abc', 'foo'); + st.equal(channel.has('abc'), true, 'non object value that exists yields true'); + + st.end(); + }); + + t.test('get', function (st) { + var channel = getSideChannelList(); + var o = {}; + st.equal(channel.get(o), undefined, 'nonexistent value yields undefined'); + + var data = {}; + channel.set(o, data); + st.equal(channel.get(o), data, '"get" yields data set by "set"'); + + st.end(); + }); + + t.test('set', function (st) { + var channel = getSideChannelList(); + var o = function () {}; + st.equal(channel.get(o), undefined, 'value not set'); + + channel.set(o, 42); + st.equal(channel.get(o), 42, 'value was set'); + + channel.set(o, Infinity); + st.equal(channel.get(o), Infinity, 'value was set again'); + + var o2 = {}; + channel.set(o2, 17); + st.equal(channel.get(o), Infinity, 'o is not modified'); + st.equal(channel.get(o2), 17, 'o2 is set'); + + channel.set(o, 14); + st.equal(channel.get(o), 14, 'o is modified'); + st.equal(channel.get(o2), 17, 'o2 is not modified'); + + st.end(); + }); + + t.test('delete', function (st) { + var channel = getSideChannelList(); + var o = {}; + st.equal(channel['delete']({}), false, 'nonexistent value yields false'); + + channel.set(o, 42); + st.equal(channel.has(o), true, 'value is set'); + + st.equal(channel['delete']({}), false, 'nonexistent value still yields false'); + + st.equal(channel['delete'](o), true, 'deleted value yields true'); + + st.equal(channel.has(o), false, 'value is no longer set'); + + st.end(); + }); + + t.test('delete: first node in a multi-node list', function (st) { + var channel = getSideChannelList(); + + channel.set('a', 1); + channel.set('b', 2); + + st.equal(channel['delete']('b'), true, 'deleting first data node yields true'); + + st.equal(channel.has('a'), true, 'second node is still present after deleting first'); + st.equal(channel.get('a'), 1, 'second node value is intact after deleting first'); + st.equal(channel.has('b'), false, 'deleted node is gone'); + + st.end(); + }); + + t.test('delete: last remaining node empties the list', function (st) { + var channel = getSideChannelList(); + + channel.set('a', 1); + channel.set('b', 2); + + st.equal(channel['delete']('b'), true, 'delete first node'); + st.equal(channel['delete']('a'), true, 'delete second (last) node'); + + st.equal(channel.has('a'), false, 'a is gone'); + st.equal(channel.has('b'), false, 'b is gone'); + st.equal(channel.get('a'), undefined, 'get a yields undefined'); + + channel.set('c', 3); + st.equal(channel.get('c'), 3, 'can set new values after emptying'); + + st.end(); + }); + + t.test('delete: middle node in a multi-node list', function (st) { + var channel = getSideChannelList(); + + channel.set('a', 1); + channel.set('b', 2); + channel.set('c', 3); + + st.equal(channel['delete']('b'), true, 'deleting middle node yields true'); + + st.equal(channel.get('a'), 1, 'first node still intact'); + st.equal(channel.has('b'), false, 'middle node is gone'); + st.equal(channel.get('c'), 3, 'last node still intact'); + + st.end(); + }); + + t.end(); +}); diff --git a/node_modules/side-channel-list/tsconfig.json b/node_modules/side-channel-list/tsconfig.json new file mode 100644 index 0000000..d9a6668 --- /dev/null +++ b/node_modules/side-channel-list/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "@ljharb/tsconfig", + "compilerOptions": { + "target": "es2021", + }, + "exclude": [ + "coverage", + ], +} |