Skip to content

Commit

Permalink
[types] improve types
Browse files Browse the repository at this point in the history
  • Loading branch information
ljharb committed Dec 9, 2024
1 parent b78336b commit 0c54356
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 37 deletions.
27 changes: 6 additions & 21 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,12 @@
declare namespace getSideChannel {
type Key = unknown;
type ListNode<T> = {
key: Key;
next: ListNode<T>;
value: T;
};
type RootNode<T> = {
key: object;
next: null | ListNode<T>;
};
function listGetNode<T>(list: RootNode<T>, key: ListNode<T>['key']): ListNode<T> | void;
function listGet<T>(objects: RootNode<T>, key: ListNode<T>['key']): T | void;
function listSet<T>(objects: RootNode<T>, key: ListNode<T>['key'], value: T): void;
function listHas<T>(objects: RootNode<T>, key: ListNode<T>['key']): boolean;

type Channel = {
assert: (key: Key) => void;
has: (key: Key) => boolean;
get: <T>(key: Key) => T;
set: <T>(key: Key, value: T) => void;
type Channel<V, K> = {
assert: (key: K) => void;
has: (key: K) => boolean;
get: (key: K) => V | undefined;
set: (key: K, value: V) => void;
}
}

declare function getSideChannel(): getSideChannel.Channel;
declare function getSideChannel<V, K>(): getSideChannel.Channel<V, K>;

export = getSideChannel;
31 changes: 22 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,27 @@ var $TypeError = require('es-errors/type');
var $WeakMap = GetIntrinsic('%WeakMap%', true);
var $Map = GetIntrinsic('%Map%', true);

/** @template T @typedef {<T extends (this: any, ...args: any[]) => any>(this: ThisParameterType<T>, ...args: Parameters<T>) => ReturnType<T>} CallBind */

/** @type {CallBind<<K extends object, V>(this: WeakMap<K, V>, key: K) => V>} */
var $weakMapGet = callBound('WeakMap.prototype.get', true);
/** @type {CallBind<typeof WeakMap.prototype.set>} */
var $weakMapSet = callBound('WeakMap.prototype.set', true);
/** @type {CallBind<typeof WeakMap.prototype.has>} */
var $weakMapHas = callBound('WeakMap.prototype.has', true);
/** @type {CallBind<typeof Map.prototype.get>} */
var $mapGet = callBound('Map.prototype.get', true);
/** @type {CallBind<typeof Map.prototype.set>} */
var $mapSet = callBound('Map.prototype.set', true);
/** @type {CallBind<typeof Map.prototype.has>} */
var $mapHas = callBound('Map.prototype.has', true);

/*
* 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('.').listGetNode} */
/** @type {import('./list.d.ts').listGetNode} */
var listGetNode = function (list, key) { // eslint-disable-line consistent-return
/** @type {typeof list | NonNullable<(typeof list)['next']>} */
var prev = list;
Expand All @@ -37,37 +45,41 @@ var listGetNode = function (list, key) { // eslint-disable-line consistent-retur
}
};

/** @type {import('.').listGet} */
/** @type {import('./list.d.ts').listGet} */
var listGet = function (objects, key) {
var node = listGetNode(objects, key);
return node && node.value;
};
/** @type {import('.').listSet} */
/** @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('.').ListNode<typeof value>} */ ({ // eslint-disable-line no-param-reassign, no-extra-parens
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('.').listHas} */
/** @type {import('./list.d.ts').listHas} */
var listHas = function (objects, key) {
return !!listGetNode(objects, key);
};

/** @type {import('.')} */
module.exports = function getSideChannel() {
/** @type {WeakMap<object, unknown>} */ var $wm;
/** @type {Map<object, unknown>} */ var $m;
/** @type {import('.').RootNode<unknown>} */ var $o;
/** @typedef {ReturnType<typeof getSideChannel>} Channel */
/** @typedef {Parameters<Channel['get']>[0]} K */
/** @typedef {Parameters<Channel['set']>[1]} V */

/** @type {WeakMap<K & object, V> | undefined} */ var $wm;
/** @type {Map<K, V> | undefined} */ var $m;
/** @type {import('./list.d.ts').RootNode<V, K> | undefined} */ var $o;

/** @type {import('.').Channel} */
/** @type {Channel} */
var channel = {
assert: function (key) {
if (!channel.has(key)) {
Expand Down Expand Up @@ -125,5 +137,6 @@ module.exports = function getSideChannel() {
}
}
};
// @ts-expect-error TODO: figure out why this is erroring
return channel;
};
14 changes: 14 additions & 0 deletions list.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type ListNode<T, K> = {
key: K;
next: ListNode<T, K>;
value: T;
};
type RootNode<T, K> = {
key: object;
next: null | ListNode<T, K>;
};

export function listGetNode<T, K>(list: RootNode<T, K>, key: ListNode<T, K>['key']): ListNode<T, K> | void;
export function listGet<T, K>(objects: RootNode<T, K>, key: ListNode<T, K>['key']): T | void;
export function listSet<T, K>(objects: RootNode<T, K>, key: ListNode<T, K>['key'], value: T): void;
export function listHas<T, K>(objects: RootNode<T, K>, key: ListNode<T, K>['key']): boolean;
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@
"url": "https://github.com/ljharb/side-channel/issues"
},
"homepage": "https://github.com/ljharb/side-channel#readme",
"dependencies": {
"call-bind": "^1.0.8",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"devDependencies": {
"@ljharb/eslint-config": "^21.1.1",
"@ljharb/tsconfig": "^0.2.2",
Expand All @@ -60,12 +66,6 @@
"tape": "^5.9.0",
"typescript": "next"
},
"dependencies": {
"call-bind": "^1.0.8",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"auto-changelog": {
"output": "CHANGELOG.md",
"template": "keepachangelog",
Expand Down
2 changes: 1 addition & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"extends": "@ljharb/tsconfig",
"compilerOptions": {
"target": "es2021", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "es2021",
},
"exclude": [
"coverage",
Expand Down

0 comments on commit 0c54356

Please sign in to comment.