@webreflection/utils 0.2.7 → 0.2.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,38 +5,12 @@
5
5
  <sup>**Social Media Photo by [benjamin lehman](https://unsplash.com/@abject) on [Unsplash](https://unsplash.com/)**</sup>
6
6
 
7
7
 
8
- A [collection](./src/) of utility functions.
8
+ A [collection](./src/) of utility functions:
9
9
 
10
- ```js
11
- // example: a shim based on ArrayBuffer if native is `false`
12
- import { SharedArrayBuffer, native } from '@webreflection/utils/shared-array-buffer';
10
+ * **[bound-once](https://github.com/WebReflection/utils/tree/main/src#bound-once)** - to retrieve unique bound methods per realm
11
+ * **[bound](https://github.com/WebReflection/utils/tree/main/src#bound)** - to retrieve one-off bound methods
12
+ * **[shared-array-buffer](https://github.com/WebReflection/utils/tree/main/src#shared-array-buffer)** - to simulate *SAB* when not available
13
+ * **[sticky](https://github.com/WebReflection/utils/tree/main/src#sticky)** - to stick once per realm anything useful
14
+ * **[with-resolvers](https://github.com/WebReflection/utils/tree/main/src#with-resolvers)** - a self bound `Promise.withResolver()` for older runtimes
13
15
 
14
- // example: self bound Promise.withResolvers()
15
- import withResolvers from '@webreflection/utils/with-resolvers';
16
-
17
- const { promise, resolve, reject } = withResolvers();
18
-
19
- // example: any object bound method
20
- import bound from '@webreflection/utils/bound';
21
-
22
- const { all, resolve } = bound(Promise);
23
- all([1, 2, 3]);
24
- resolve(4);
25
-
26
-
27
- // example: any object bound method is identical
28
- // particularly useful for listeners identity
29
- import boundOnce from '@webreflection/utils/bound-once';
30
-
31
- const { all, resolve } = boundOnce(Promise);
32
- all([1, 2, 3]);
33
- resolve(4);
34
-
35
- boundOnce(Promise).all === all;
36
- boundOnce(Promise).resolve === resolve;
37
-
38
- // example: always retrieve the first time data/module
39
- import sticky from '@webreflection/utils/sticky';
40
-
41
- export default sticky('@module/name', { always: 'same' });
42
- ```
16
+ MIT style License.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webreflection/utils",
3
- "version": "0.2.7",
3
+ "version": "0.2.9",
4
4
  "type": "module",
5
5
  "types": {
6
6
  "./bound-once": "./types/bound-once.d.ts",
package/src/README.md ADDED
@@ -0,0 +1,79 @@
1
+ # @webreflection/utils
2
+
3
+ Each utility can be loaded from a *CDN* via either `https://esm.run/@webreflection/utils/{{UTILITY}}` or `https://cdn.jsdelivr.net/npm/@webreflection/utils/src/{{UTILITY}}.js`.
4
+
5
+
6
+ This document describes each utility separately.
7
+
8
+ ## bound-once
9
+
10
+ This is equivalent to **bound**, except each bound method is created only once. It is useful when bound method identity must be preserved across multiple calls.
11
+
12
+ This variant uses **sticky** to ensure that weakly referenced targets always produce the same bound method within the same realm.
13
+
14
+ ## bound
15
+
16
+ This utility provides an object-destructuring syntax shortcut for binding methods.
17
+
18
+ ```js
19
+ import bound from '@webreflection/utils/bound';
20
+
21
+ const { all, resolve } = bound(Promise);
22
+ all([1, 2, 3]);
23
+ resolve(4);
24
+ ```
25
+
26
+ The **bound-once** variant ensures that repeated accesses, such as `boundOnce(Promise).all`, always return the same bound method.
27
+
28
+ ## shared-array-buffer
29
+
30
+ This utility provides an unobtrusive *SAB* (*SharedArrayBuffer*) shim based on the default *ArrayBuffer*, with `grow(length)` and `growable` additions.
31
+
32
+ This class can be used to simulate *SAB* capabilities.
33
+
34
+ The module exports both `SharedArrayBuffer` and `native`. The `native` *boolean* indicates whether the returned constructor is the platform implementation or the shim.
35
+
36
+ ## sticky
37
+
38
+ Based on `Symbol.for(name)`, this utility helps modules that might be embedded multiple times across projects avoid conflicts in their internal logic. It preserves the assumption that a module is imported only *once* per application.
39
+
40
+ ```js
41
+ import sticky from '@webreflection/utils/sticky';
42
+
43
+ // will be created and discarded ASAP
44
+ // if embedded multiple times
45
+ const computed = new WeakMap;
46
+
47
+ // module will always point at the very first computed
48
+ const [module, known] = sticky(
49
+ '@my-project/known-references',
50
+ ref => {
51
+ // ensure this reference is processed only once in this realm
52
+ if (computed.has(ref)) return computed.get(ref);
53
+
54
+ // compute the value once, then reuse it on future calls
55
+ const costlyComputation = somethingNeededOnce(ref);
56
+ computed.set(ref, costlyComputation);
57
+ return costlyComputation;
58
+ },
59
+ );
60
+
61
+ if (known) console.warn('embedded multiple times');
62
+
63
+ export default module;
64
+ ```
65
+
66
+
67
+ ## with-resolvers
68
+
69
+ This utility returns a self-bound `Promise.withResolvers()` implementation that also works on older Android WebView runtimes.
70
+
71
+ ```js
72
+ import withResolvers from '@webreflection/utils/with-resolvers';
73
+
74
+ const { promise, resolve, reject } = withResolvers();
75
+
76
+ setTimeout(resolve, 0, 42);
77
+
78
+ export default promise;
79
+ ```
package/src/bound-once.js CHANGED
@@ -1,17 +1,10 @@
1
1
  //@ts-check
2
2
 
3
- const $ = Symbol.for('@webreflection/utils/bound-once');
3
+ import sticky from './sticky.js';
4
4
 
5
- // @ts-ignore
6
- const methods = globalThis[$] || Object.defineProperty(
7
- globalThis,
8
- $,
9
- { value: new WeakMap },
10
- )[$];
5
+ const methods = /** @type {WeakMap<object, Map<string | symbol, (...args: any[]) => unknown>>} */ (new WeakMap);
11
6
 
12
- /**
13
- * @type {ProxyHandler<any>}
14
- */
7
+ /** @type {ProxyHandler<any>} */
15
8
  const handler = {
16
9
  get(target, prop) {
17
10
  const known = /** @type {Map<string | symbol, (...args: any[]) => unknown>} */ (methods.get(target));
@@ -21,12 +14,15 @@ const handler = {
21
14
  }
22
15
  };
23
16
 
24
- /**
25
- * @template {object} T
26
- * @param {T} target
27
- * @returns {import('./bound.js').Bound<T>}
28
- */
29
- export default target => {
30
- if (!methods.has(target)) methods.set(target, new Map);
31
- return new Proxy(target, handler);
32
- };
17
+ export default sticky(
18
+ '@webreflection/utils/bound-once',
19
+ /**
20
+ * @template {object} T
21
+ * @param {T} target
22
+ * @returns {import('./bound.js').Bound<T>}
23
+ */
24
+ target => {
25
+ if (!methods.has(target)) methods.set(target, new Map);
26
+ return new Proxy(target, handler);
27
+ },
28
+ )[0];
package/src/sticky.js CHANGED
@@ -13,15 +13,12 @@ const { for: symbolFor } = Symbol;
13
13
  * @returns {[T, boolean]} the passed `value` or the previous one as first entry, a boolean indicating if it was known or not
14
14
  */
15
15
  export default (name, value, global = globalThis) => {
16
- /** @type {symbol} */
17
16
  const symbol = symbolFor(name);
18
- const known = symbol in global;
17
+ // @ts-ignore
18
+ const known = global[symbol];
19
19
  return [
20
- known ?
21
- // @ts-ignore
22
- global[symbol] :
23
- // @ts-ignore
24
- defineProperty(global, symbol, { value })[symbol],
25
- known,
20
+ // @ts-ignore
21
+ known ?? defineProperty(global, symbol, { value })[symbol],
22
+ !!known,
26
23
  ];
27
24
  };
@@ -1,2 +1,7 @@
1
+ /**
2
+ * @template {object} T
3
+ * @param {T} target
4
+ * @returns {import('./bound.js').Bound<T>}
5
+ */
1
6
  declare function _default<T extends object>(target: T): import("./bound.js").Bound<T>;
2
7
  export default _default;