-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This package provides a `KeySetMap` class similar to the `Trie` API provided by the `@wry/trie` package, except the keys passed to `lookup` or `peek` have _set_ semantics rather than _sequence_ semantics.
- Loading branch information
Showing
11 changed files
with
846 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
|
||
# Runtime data | ||
pids | ||
*.pid | ||
*.seed | ||
|
||
# Directory for instrumented libs generated by jscoverage/JSCover | ||
lib-cov | ||
|
||
# Coverage directory used by tools like istanbul | ||
coverage | ||
|
||
# nyc test coverage | ||
.nyc_output | ||
|
||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | ||
.grunt | ||
|
||
# node-waf configuration | ||
.lock-wscript | ||
|
||
# Compiled binary addons (http://nodejs.org/api/addons.html) | ||
build/Release | ||
|
||
# Dependency directories | ||
node_modules | ||
jspm_packages | ||
|
||
# Optional npm cache directory | ||
.npm | ||
|
||
# Optional REPL history | ||
.node_repl_history | ||
|
||
# Ignore generated TypeScript files. | ||
lib | ||
|
||
# Cache for rollup-plugin-typescript2 | ||
.rpt2_cache |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
/node_modules | ||
/lib/tests | ||
tsconfig.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
# @wry/key-set-map | ||
|
||
Whereas the `@wry/trie` package associates values with _sequences_ of keys, the | ||
`@wry/key-set-map` package and its `KeySetMap` class provide a similar | ||
capability for _sets_ of keys, so the order of the input keys is no longer | ||
important. | ||
|
||
As with a traditional [Trie](https://en.wikipedia.org/wiki/Trie), lookups and | ||
insertions take linear time in the size of the input set, and peek-like | ||
operations can often bail out much more quickly, without having to look at all | ||
the input set elements. | ||
|
||
Since JavaScript `Set` and `Map` containers maintain insertion order, two | ||
equivalent sets (containing identical elements) can nevertheless be detectably | ||
different if their keys were inserted in a different order. Deciding which of | ||
the orders is "correct" or "canonical" is a fool's errand, possible only when | ||
there is an inherent total ordering among the elements, suggesting a | ||
sorting-based strategy. | ||
|
||
Because sorting is tempting as a strategy for turning sets into | ||
canonically-ordered sequences, it's important to stress: this implementation | ||
works without sorting set elements, and without requiring the elements to be | ||
comparable. In fact, the lookup algorithm is asymptotically faster than it would | ||
be if the keys had to be sorted before lookup. | ||
|
||
Finally, to avoid taking any position on which ordering of elements is | ||
canonical, this implementation never grants direct access to any previously | ||
provided sets. Instead of attempting to return a canonical `Set`, the keys of | ||
the set are associated with an arbitrary `TData` value, which is all you get | ||
when you look up a set of keys. | ||
|
||
## Memory management | ||
|
||
When `WeakRef` and `FinalizationRegistry` are available, the `KeySetMap` class | ||
automatically reclaims internal memory associated with sets containing keys that | ||
have been garbage collected. | ||
|
||
To that end, when keys can be garbage collected, the `KeySetMap` takes care not | ||
to retain them strongly, acting like a `WeakMap` for object keys and like a | ||
`Map` for non-object keys. In other words, `KeySetMap` does not prevent its | ||
(object) keys from being garbage collected, if they are otherwise eligible. | ||
|
||
By passing `false` for the `weakness` parameter to the `KeySetMap` constructor, | ||
you can disable weak-key-related functionality, so the `KeySetMap` will behave | ||
like a `Map` for all keys, regardless of whether they are objects or primitive. | ||
This mode is not encouraged for production, but may be useful for testing, | ||
debugging, or other diagnostic purposes. | ||
|
||
Any `TData` objects allocated by the `KeySetMap` may outlive their associated | ||
sets of keys, and retaining a strong reference to the `TData` object by itself | ||
does not prevent garbage collection and removal of object keys. However, as long | ||
as all keys remain reachable and are not removed from the `KeySetMap` with | ||
`remove` or `removeSet`, the set of keys will remain in the `KeySetMap` and thus | ||
retain a reference to the associated `TData`. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
{ | ||
"name": "@wry/key-set-map", | ||
"private": true, | ||
"version": "0.1.0", | ||
"author": "Ben Newman <[email protected]>", | ||
"description": "Trie-like data structure using sets rather than sequences of keys", | ||
"license": "MIT", | ||
"type": "module", | ||
"main": "lib/bundle.cjs", | ||
"module": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"keywords": [], | ||
"homepage": "https://github.com/benjamn/wryware", | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/benjamn/wryware.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/benjamn/wryware/issues" | ||
}, | ||
"scripts": { | ||
"build": "npm run clean && npm run tsc && npm run rollup", | ||
"clean": "rimraf lib", | ||
"tsc": "tsc -p tsconfig.json", | ||
"rollup": "rollup -c rollup.config.js", | ||
"prepare": "npm run build", | ||
"test:cjs": "../../shared/test.sh lib/tests/bundle.cjs", | ||
"test:esm": "../../shared/test.sh lib/tests/bundle.js", | ||
"test": "npm run test:esm && npm run test:cjs" | ||
}, | ||
"dependencies": { | ||
"tslib": "^2.3.0" | ||
}, | ||
"engines": { | ||
"node": ">=8" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { build } from "../../shared/rollup.config.js"; | ||
|
||
// This package doesn't use the lib/es5 directory, so we need to override the | ||
// default export from ../../shared/rollup.config.js (as we also do in the | ||
// @wry/equality package). | ||
export default [ | ||
build( | ||
"lib/index.js", | ||
"lib/bundle.cjs", | ||
"cjs" | ||
), | ||
build( | ||
"lib/tests/main.js", | ||
"lib/tests/bundle.js", | ||
"esm" | ||
), | ||
build( | ||
"lib/tests/main.js", | ||
"lib/tests/bundle.cjs", | ||
"cjs" | ||
), | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
export const arrayForEach = Array.prototype.forEach; | ||
|
||
export const { | ||
prototype: { | ||
hasOwnProperty, | ||
toString: objectToString, | ||
}, | ||
} = Object; | ||
|
||
// If no makeData function is supplied, the looked-up data will be an empty, | ||
// null-prototype Object. | ||
export function defaultMakeData(): any { | ||
return Object.create(null); | ||
} | ||
|
||
export function isObjRef(value: any): value is object { | ||
if (value) { | ||
switch (typeof value) { | ||
case "object": | ||
case "function": | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
const SET_TO_STRING_TAG = objectToString.call(new Set); | ||
|
||
export function assertSet(set: any): asserts set is Set<any> { | ||
const toStringTag = objectToString.call(set); | ||
if (toStringTag !== SET_TO_STRING_TAG) { | ||
throw new TypeError(`Not a Set: ${toStringTag}`); | ||
} | ||
} | ||
|
||
const KNOWN: unique symbol = Symbol("KeySetMap.KNOWN"); | ||
|
||
export function makeKnownWeakRef<T extends object>(key: T): WeakRef<T> { | ||
return Object.assign(new WeakRef(key), { [KNOWN]: true }); | ||
} | ||
|
||
export function isKnownWeakRef(ref: unknown): ref is WeakRef<object> { | ||
return ( | ||
ref instanceof WeakRef && | ||
KNOWN in ref && | ||
ref[KNOWN] === true | ||
); | ||
} |
Oops, something went wrong.