1.1.5 • Published 8 months ago

weaken-it v1.1.5

Weekly downloads
-
License
MIT
Repository
github
Last release
8 months ago

weaken-it

minzipped typescript

Lightweight tree-shakeable WeakMap utility functions and related patterns, with typescript support.

Every weakness contains within itself a strength Shūsaku Endō

Dandelion by Herbert Goetsch Photo by Herbert Goetsch on Unsplash


:man_technologist: Installation

Npm

npm i weaken-it

CDN

<script type="module">
const { wit } = await import("https://cdn.jsdelivr.net/npm/weaken-it@latest")

// store to context
wit(SomeReference, ContextNamespace, AnyValue)

// retrieve
wit(SomeReference, ContextNamespace)

</script>

:wrench: How it works

At its core it's just a temporary namespaced key-value store built on top of native js WeakMap and Map, using a set of personal conventions enforced by weakenIt() function. Both WeakMap and Map were chosen over plain objects for their advantages in terms of r/w speed and key flexibility.

  • Creates a WeakMap, wStore
  • WeakMap ensures that each instance is stored once and its associated context expires with it
  • weakenIt ensures that each Map context is stored / recreated only once and always reused
  • Then weakenIt, or even shorter wit, stores / gets any key-value from the related context
  • When reference is lost or wStore.prototype.deleted || wDel, its context gets garbage-collected

:thinking: Why

I was very excited about WeakRef and FinalizationRegistry coming to javascript but both their behaviours are not yet guaranteed, making them very hard to reason about, at least for me.

:ring_buoy: WeakMap and WeakSet to the rescue!

  • They ensure stored data will expire after the bound instance, or will always be available as long the associated reference exists
  • They enable patterns I reach for when I need to extend libraries, js natives, work with dom, store temporary data or when I'm generally concerned about potential memory leaks
  • It can safely bridge context data inside closures or where unreachable
  • They're fast, native, memory-efficient by nature, fully supported and reliable
  • They give me peace of mind :relieved:

:muscle: Usage

For more examples, please refer to tests folder.

import { weakenIt } from 'weaken-it'

// augment an external library or native
class Example extends SomeLibraryOrNative {

  constructor(extraData, ...libraryRequired) {
    super(...libraryRequired)

    // extraData never outlives the instance
    weakenIt(this, 'temp', extraData + 'Example constructor')
  }

  overridden(...methodArgs) {
    // bridged inside
    const extraData = weakenIt(this, 'temp')    
    doSomethingWith(temp)

    // still works without modifying the original implementation
    return SomeLibraryOrNative.prototype.overridden.apply(this, methodArgs)
  }
}

let exampleInstance = new Example(
  'extra data from: ',
  'library needed data'
)

function useExtraData() {
  console.log(weakenIt(example, 'temp'))
}

useExtraData()
// extra data from: Example constructor

example = null 
useExtraData()
// undefined (gc'ed)

:toolbox: Available exports

Core

  • weakenIt, core function to interact with contexts
  • wStore, stores all contexts

Shortcuts

  • wit, alias to weakenIt
  • wDel, hard reset context
  • wCtx, gets the entire context
  • wCast, casts a copy of the context as object
  • wSure, upsert if stored is nullish
  • wMap, new Map(), dirt-cheap iterable WeakMap
  • wSet, new Set(), dirt-cheap iterable WeakSet
  • wKV, creates a Object.create(null)
  • wArr, creates []
  • wObj, creates {}

Utils

  • wMemo, memoized fn
  • wCount, global counter

:ballot_box_with_check: TODO

x Import and standardize other patterns x Randomize tests x Documentation

Disclaimer

This library is very opinionated, mainly bult for reusability between personal projects. It encapsulates and summarizes some of my most recurring personal approaches involving native WeakMap, which I really :heart:

1.1.5

8 months ago

1.1.4

8 months ago

1.1.3

8 months ago

1.1.2

8 months ago

1.1.1

8 months ago

1.1.0

8 months ago

1.0.0

8 months ago