@pistonite/pure 0.0.20 → 0.21.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pistonite/pure",
3
- "version": "0.0.20",
3
+ "version": "0.21.0",
4
4
  "type": "module",
5
5
  "description": "Pure TypeScript libraries for my projects",
6
6
  "homepage": "https://github.com/Pistonite/pure",
@@ -0,0 +1,8 @@
1
+ /**
2
+ * # pure/memory
3
+ * JS memory utilities
4
+ *
5
+ * @module
6
+ */
7
+ export { cell, type CellConstructor, type Cell } from "./cell.ts";
8
+ export { persist, type PersistConstructor, type Persist } from "./persist.ts";
@@ -0,0 +1,139 @@
1
+ export type ExternalWeakRef<TUnderlying, TType> = {
2
+ /**
3
+ * A marker value for the underlying object type.
4
+ *
5
+ * This is commonly a string literal or a symbol.
6
+ */
7
+ type: TType;
8
+
9
+ /**
10
+ * The underlying object reference.
11
+ */
12
+ ref: TUnderlying | undefined;
13
+
14
+ /**
15
+ * Free the underlying object.
16
+ */
17
+ free: () => void;
18
+
19
+ /**
20
+ * Update the underlying object reference.
21
+ *
22
+ * If the new reference is the same as the old one, nothing will happen.
23
+ * If the old reference is not undefined, it will be freed.
24
+ */
25
+ set: (value: TUnderlying | undefined) => void;
26
+ };
27
+
28
+ export type ExternalWeakRefConstructor<TUnderlying, TType> = {
29
+ /**
30
+ * A marker value for the underlying object type.
31
+ *
32
+ * This is commonly a string literal or a symbol.
33
+ */
34
+ marker: TType;
35
+
36
+ /**
37
+ * The function to free the underlying object.
38
+ */
39
+ free: (obj: TUnderlying) => void;
40
+ };
41
+
42
+ /**
43
+ * Create a weak reference type for managing externally memory-managed object. This means
44
+ * the objects needs to be freed manually by the external code.
45
+ *
46
+ * The `marker` option is used to distinguish between different types of weak references
47
+ * with the same underlying representation for the reference.
48
+ *
49
+ * Note that the underlying representation should not be undefined-able!
50
+ *
51
+ * ## Example
52
+ * ```typescript
53
+ * import { makeExternalWeakRefType } from "@pistonite/pure/memory";
54
+ *
55
+ * // assume `number` is the JS type used to represent the external object
56
+ * // for example, this can be a pointer to a C++ object
57
+ * declare function freeFoo(obj: number) => void;
58
+ *
59
+ * // some function that allocates a foo object externally and returns
60
+ * // a reference
61
+ * declare function getFoo(): number;
62
+ *
63
+ * const makeFooRef = makeExternalWeakRefType({
64
+ * marker: "foo",
65
+ * free: (obj) => {
66
+ * freeFoo(obj);
67
+ * }
68
+ * });
69
+ * type FooRef = ReturnType<typeof makeFooRef>;
70
+ *
71
+ * // create a reference to a foo object
72
+ * // now this reference can be passed around in JS,
73
+ * // as long as the ownership model is clear and the owner
74
+ * // remembers to free it
75
+ * const fooRef = makeFooRef(getFoo());
76
+ *
77
+ * // free the foo object when it is no longer needed
78
+ * fooRef.free();
79
+ *
80
+ * ## Updating the reference
81
+ * The `set` method will update the reference and free the old one if exists
82
+ * ```
83
+ * const fooRef = makeFooRef(getFoo());
84
+ * fooRef.set(getFoo()); // the old one will be freed, unless it is the same as the new one
85
+ * ```
86
+ *
87
+ * This has a major pitfall: If the ExternalWeakRef is shared, the new object will be accessible
88
+ * by code that has the old reference. In other words, when the reference is updated, code that
89
+ * already has the old reference will not able to know that it has changed.
90
+ *
91
+ * If this is a problem, you should use this pattern instead:
92
+ * ```typescript
93
+ * // track the "current" valid reference
94
+ * let currentRef = makeFooRef(undefined);
95
+ *
96
+ * export const getFooRef = (): FooRef => {
97
+ * // because of this function, many other places can hold
98
+ * // a valid reference to foo
99
+ * return currentRef;
100
+ * }
101
+ *
102
+ * export const updateFooRef = (newFoo: number): void => {
103
+ * // when updating the reference, we create a new weak ref and free the old one
104
+ * if (currentRef.ref === newFoo) {
105
+ * return; // always need to check if old and new are the same, otherwise we will be freeing the new one
106
+ * }
107
+ * const newRef = makeFooRef(newFoo);
108
+ * currentRef.free();
109
+ * currentRef = newRef;
110
+ *
111
+ * // now other places that hold the old reference will see it's freed
112
+ * }
113
+ * ```
114
+ */
115
+ export const makeExternalWeakRefType = <TUnderlying, TType>({
116
+ marker,
117
+ free,
118
+ }: ExternalWeakRefConstructor<TUnderlying, TType>) => {
119
+ return (
120
+ obj: TUnderlying | undefined,
121
+ ): ExternalWeakRef<TUnderlying, TType> => {
122
+ const weakRefObj = {
123
+ type: marker,
124
+ ref: obj,
125
+ free: () => {
126
+ if (weakRefObj.ref !== undefined) {
127
+ free(weakRefObj.ref);
128
+ }
129
+ },
130
+ set: (value: TUnderlying | undefined) => {
131
+ if (weakRefObj.ref !== undefined && weakRefObj.ref !== value) {
132
+ free(weakRefObj.ref);
133
+ }
134
+ weakRefObj.ref = value;
135
+ },
136
+ };
137
+ return weakRefObj;
138
+ };
139
+ };
package/src/pref/dark.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { persist } from "../sync/persist.ts";
1
+ import { persist } from "../memory/persist.ts";
2
2
  import { injectStyle } from "./injectStyle.ts";
3
3
 
4
4
  const dark = persist({
@@ -1,4 +1,4 @@
1
- import { persist } from "../sync/persist.ts";
1
+ import { persist } from "../memory/persist.ts";
2
2
 
3
3
  let supportedLocales: readonly string[] = [];
4
4
  let defaultLocale: string = "";
package/src/sync/index.ts CHANGED
@@ -13,8 +13,6 @@ export {
13
13
  export { latest, type LatestConstructor, type UpdateArgsFn } from "./latest.ts";
14
14
  export { debounce, type DebounceConstructor } from "./debounce.ts";
15
15
  export { batch, type BatchConstructor } from "./batch.ts";
16
- export { cell, type CellConstructor, type Cell } from "./cell.ts";
17
- export { persist, type PersistConstructor, type Persist } from "./persist.ts";
18
16
  export { once, type OnceConstructor } from "./once.ts";
19
17
 
20
18
  // types
File without changes
File without changes