@stencil/store 2.2.1 → 2.2.3-dev.1785970285.b07d6c8

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/dist/index.cjs CHANGED
@@ -1,15 +1,38 @@
1
1
  'use strict';
2
2
 
3
- var core = require('@stencil/core');
3
+ var StencilCore = require('@stencil/core');
4
4
 
5
- const appendToMap = (map, propName, value) => {
6
- const items = map.get(propName);
7
- if (!items) {
8
- map.set(propName, [value]);
5
+ function _interopNamespaceDefault(e) {
6
+ var n = Object.create(null);
7
+ if (e) {
8
+ Object.keys(e).forEach(function (k) {
9
+ if (k !== 'default') {
10
+ var d = Object.getOwnPropertyDescriptor(e, k);
11
+ Object.defineProperty(n, k, d.get ? d : {
12
+ enumerable: true,
13
+ get: function () { return e[k]; }
14
+ });
15
+ }
16
+ });
17
+ }
18
+ n.default = e;
19
+ return Object.freeze(n);
20
+ }
21
+
22
+ var StencilCore__namespace = /*#__PURE__*/_interopNamespaceDefault(StencilCore);
23
+
24
+ const appendToMap = (map, refsByValue, propName, value) => {
25
+ let ref = refsByValue.get(value);
26
+ if (!ref) {
27
+ ref = new WeakRef(value);
28
+ refsByValue.set(value, ref);
9
29
  }
10
- else if (!items.includes(value)) {
11
- items.push(value);
30
+ let refs = map.get(propName);
31
+ if (!refs) {
32
+ refs = new Set();
33
+ map.set(propName, refs);
12
34
  }
35
+ refs.add(ref);
13
36
  };
14
37
  const debounce = (fn, ms) => {
15
38
  let timeoutId;
@@ -35,34 +58,58 @@ const debounce = (fn, ms) => {
35
58
  */
36
59
  const isConnected = (maybeElement) => !('isConnected' in maybeElement) || maybeElement.isConnected;
37
60
  const cleanupElements = debounce((map) => {
38
- for (let key of map.keys()) {
39
- map.set(key, map.get(key).filter(isConnected));
40
- }
61
+ map.forEach((refs, key) => {
62
+ const nextRefs = new Set();
63
+ refs.forEach((ref) => {
64
+ const elm = ref.deref();
65
+ if (elm && isConnected(elm))
66
+ nextRefs.add(ref);
67
+ });
68
+ map.set(key, nextRefs);
69
+ });
41
70
  }, 2_000);
71
+ const core = StencilCore__namespace;
72
+ const forceUpdate = core.forceUpdate;
73
+ const getRenderingRef = core.getRenderingRef;
42
74
  const stencilSubscription = () => {
43
- if (typeof core.getRenderingRef !== 'function') {
75
+ if (typeof getRenderingRef !== 'function' || typeof forceUpdate !== 'function') {
44
76
  // If we are not in a stencil project, we do nothing.
45
77
  // This function is not really exported by @stencil/core.
46
78
  return {};
47
79
  }
80
+ const ensureForceUpdate = forceUpdate;
81
+ const ensureGetRenderingRef = getRenderingRef;
82
+ const refsByElement = new WeakMap();
48
83
  const elmsToUpdate = new Map();
49
84
  return {
50
85
  dispose: () => elmsToUpdate.clear(),
51
86
  get: (propName) => {
52
- const elm = core.getRenderingRef();
87
+ const elm = ensureGetRenderingRef();
53
88
  if (elm) {
54
- appendToMap(elmsToUpdate, propName, elm);
89
+ appendToMap(elmsToUpdate, refsByElement, propName, elm);
55
90
  }
56
91
  },
57
92
  set: (propName) => {
58
- const elements = elmsToUpdate.get(propName);
59
- if (elements) {
60
- elmsToUpdate.set(propName, elements.filter(core.forceUpdate));
93
+ const refs = elmsToUpdate.get(propName);
94
+ if (refs) {
95
+ const nextRefs = new Set();
96
+ refs.forEach((ref) => {
97
+ const elm = ref.deref();
98
+ if (elm && ensureForceUpdate(elm))
99
+ nextRefs.add(ref);
100
+ });
101
+ elmsToUpdate.set(propName, nextRefs);
61
102
  }
62
103
  cleanupElements(elmsToUpdate);
63
104
  },
64
105
  reset: () => {
65
- elmsToUpdate.forEach((elms) => elms.forEach(core.forceUpdate));
106
+ elmsToUpdate.forEach((refs) => {
107
+ refs.forEach((ref) => {
108
+ const elm = ref.deref();
109
+ if (elm)
110
+ ensureForceUpdate(elm);
111
+ });
112
+ });
66
113
  cleanupElements(elmsToUpdate);
67
114
  },
68
115
  };
@@ -70,8 +117,11 @@ const stencilSubscription = () => {
70
117
 
71
118
  const unwrap = (val) => (typeof val === 'function' ? val() : val);
72
119
  const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) => {
73
- const unwrappedState = unwrap(defaultState);
74
- let states = new Map(Object.entries(unwrappedState ?? {}));
120
+ const resolveDefaultState = () => (unwrap(defaultState) ?? {});
121
+ const initialState = resolveDefaultState();
122
+ let states = new Map(Object.entries(initialState));
123
+ const proxyAvailable = typeof Proxy !== 'undefined';
124
+ const plainState = proxyAvailable ? null : {};
75
125
  const handlers = {
76
126
  dispose: [],
77
127
  get: [],
@@ -83,7 +133,10 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
83
133
  const reset = () => {
84
134
  // When resetting the state, the default state may be a function - unwrap it to invoke it.
85
135
  // otherwise, the state won't be properly reset
86
- states = new Map(Object.entries(unwrap(defaultState) ?? {}));
136
+ states = new Map(Object.entries(resolveDefaultState()));
137
+ if (!proxyAvailable) {
138
+ syncPlainStateKeys();
139
+ }
87
140
  handlers.reset.forEach((cb) => cb());
88
141
  };
89
142
  const dispose = () => {
@@ -100,12 +153,14 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
100
153
  const oldValue = states.get(propName);
101
154
  if (shouldUpdate(value, oldValue, propName)) {
102
155
  states.set(propName, value);
156
+ if (!proxyAvailable) {
157
+ ensurePlainProperty(propName);
158
+ }
103
159
  handlers.set.forEach((cb) => cb(propName, value, oldValue));
104
160
  }
105
161
  };
106
- const state = (typeof Proxy === 'undefined'
107
- ? {}
108
- : new Proxy(unwrappedState, {
162
+ const state = (proxyAvailable
163
+ ? new Proxy(initialState, {
109
164
  get(_, propName) {
110
165
  return get(propName);
111
166
  },
@@ -125,7 +180,11 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
125
180
  set(propName, value);
126
181
  return true;
127
182
  },
128
- }));
183
+ })
184
+ : (() => {
185
+ syncPlainStateKeys();
186
+ return plainState;
187
+ })());
129
188
  const on = (eventName, callback) => {
130
189
  handlers[eventName].push(callback);
131
190
  return () => {
@@ -138,7 +197,10 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
138
197
  cb(newValue);
139
198
  }
140
199
  };
141
- const resetHandler = () => cb(unwrap(defaultState)[propName]);
200
+ const resetHandler = () => {
201
+ const snapshot = resolveDefaultState();
202
+ cb(snapshot[propName]);
203
+ };
142
204
  // Register the handlers
143
205
  const unSet = on('set', setHandler);
144
206
  const unReset = on('reset', resetHandler);
@@ -181,6 +243,38 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
181
243
  changeListeners.delete(listener);
182
244
  }
183
245
  };
246
+ function ensurePlainProperty(key) {
247
+ if (proxyAvailable || !plainState) {
248
+ return;
249
+ }
250
+ if (Object.prototype.hasOwnProperty.call(plainState, key)) {
251
+ return;
252
+ }
253
+ Object.defineProperty(plainState, key, {
254
+ configurable: true,
255
+ enumerable: true,
256
+ get() {
257
+ return get(key);
258
+ },
259
+ set(value) {
260
+ set(key, value);
261
+ },
262
+ });
263
+ }
264
+ function syncPlainStateKeys() {
265
+ if (proxyAvailable || !plainState) {
266
+ return;
267
+ }
268
+ const knownKeys = new Set(states.keys());
269
+ for (const key of Object.keys(plainState)) {
270
+ if (!knownKeys.has(key)) {
271
+ delete plainState[key];
272
+ }
273
+ }
274
+ for (const key of knownKeys) {
275
+ ensurePlainProperty(key);
276
+ }
277
+ }
184
278
  return {
185
279
  state,
186
280
  get,
package/dist/index.js CHANGED
@@ -1,13 +1,17 @@
1
- import { getRenderingRef, forceUpdate } from '@stencil/core';
1
+ import * as StencilCore from '@stencil/core';
2
2
 
3
- const appendToMap = (map, propName, value) => {
4
- const items = map.get(propName);
5
- if (!items) {
6
- map.set(propName, [value]);
3
+ const appendToMap = (map, refsByValue, propName, value) => {
4
+ let ref = refsByValue.get(value);
5
+ if (!ref) {
6
+ ref = new WeakRef(value);
7
+ refsByValue.set(value, ref);
7
8
  }
8
- else if (!items.includes(value)) {
9
- items.push(value);
9
+ let refs = map.get(propName);
10
+ if (!refs) {
11
+ refs = new Set();
12
+ map.set(propName, refs);
10
13
  }
14
+ refs.add(ref);
11
15
  };
12
16
  const debounce = (fn, ms) => {
13
17
  let timeoutId;
@@ -33,34 +37,58 @@ const debounce = (fn, ms) => {
33
37
  */
34
38
  const isConnected = (maybeElement) => !('isConnected' in maybeElement) || maybeElement.isConnected;
35
39
  const cleanupElements = debounce((map) => {
36
- for (let key of map.keys()) {
37
- map.set(key, map.get(key).filter(isConnected));
38
- }
40
+ map.forEach((refs, key) => {
41
+ const nextRefs = new Set();
42
+ refs.forEach((ref) => {
43
+ const elm = ref.deref();
44
+ if (elm && isConnected(elm))
45
+ nextRefs.add(ref);
46
+ });
47
+ map.set(key, nextRefs);
48
+ });
39
49
  }, 2_000);
50
+ const core = StencilCore;
51
+ const forceUpdate = core.forceUpdate;
52
+ const getRenderingRef = core.getRenderingRef;
40
53
  const stencilSubscription = () => {
41
- if (typeof getRenderingRef !== 'function') {
54
+ if (typeof getRenderingRef !== 'function' || typeof forceUpdate !== 'function') {
42
55
  // If we are not in a stencil project, we do nothing.
43
56
  // This function is not really exported by @stencil/core.
44
57
  return {};
45
58
  }
59
+ const ensureForceUpdate = forceUpdate;
60
+ const ensureGetRenderingRef = getRenderingRef;
61
+ const refsByElement = new WeakMap();
46
62
  const elmsToUpdate = new Map();
47
63
  return {
48
64
  dispose: () => elmsToUpdate.clear(),
49
65
  get: (propName) => {
50
- const elm = getRenderingRef();
66
+ const elm = ensureGetRenderingRef();
51
67
  if (elm) {
52
- appendToMap(elmsToUpdate, propName, elm);
68
+ appendToMap(elmsToUpdate, refsByElement, propName, elm);
53
69
  }
54
70
  },
55
71
  set: (propName) => {
56
- const elements = elmsToUpdate.get(propName);
57
- if (elements) {
58
- elmsToUpdate.set(propName, elements.filter(forceUpdate));
72
+ const refs = elmsToUpdate.get(propName);
73
+ if (refs) {
74
+ const nextRefs = new Set();
75
+ refs.forEach((ref) => {
76
+ const elm = ref.deref();
77
+ if (elm && ensureForceUpdate(elm))
78
+ nextRefs.add(ref);
79
+ });
80
+ elmsToUpdate.set(propName, nextRefs);
59
81
  }
60
82
  cleanupElements(elmsToUpdate);
61
83
  },
62
84
  reset: () => {
63
- elmsToUpdate.forEach((elms) => elms.forEach(forceUpdate));
85
+ elmsToUpdate.forEach((refs) => {
86
+ refs.forEach((ref) => {
87
+ const elm = ref.deref();
88
+ if (elm)
89
+ ensureForceUpdate(elm);
90
+ });
91
+ });
64
92
  cleanupElements(elmsToUpdate);
65
93
  },
66
94
  };
@@ -68,8 +96,11 @@ const stencilSubscription = () => {
68
96
 
69
97
  const unwrap = (val) => (typeof val === 'function' ? val() : val);
70
98
  const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) => {
71
- const unwrappedState = unwrap(defaultState);
72
- let states = new Map(Object.entries(unwrappedState ?? {}));
99
+ const resolveDefaultState = () => (unwrap(defaultState) ?? {});
100
+ const initialState = resolveDefaultState();
101
+ let states = new Map(Object.entries(initialState));
102
+ const proxyAvailable = typeof Proxy !== 'undefined';
103
+ const plainState = proxyAvailable ? null : {};
73
104
  const handlers = {
74
105
  dispose: [],
75
106
  get: [],
@@ -81,7 +112,10 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
81
112
  const reset = () => {
82
113
  // When resetting the state, the default state may be a function - unwrap it to invoke it.
83
114
  // otherwise, the state won't be properly reset
84
- states = new Map(Object.entries(unwrap(defaultState) ?? {}));
115
+ states = new Map(Object.entries(resolveDefaultState()));
116
+ if (!proxyAvailable) {
117
+ syncPlainStateKeys();
118
+ }
85
119
  handlers.reset.forEach((cb) => cb());
86
120
  };
87
121
  const dispose = () => {
@@ -98,12 +132,14 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
98
132
  const oldValue = states.get(propName);
99
133
  if (shouldUpdate(value, oldValue, propName)) {
100
134
  states.set(propName, value);
135
+ if (!proxyAvailable) {
136
+ ensurePlainProperty(propName);
137
+ }
101
138
  handlers.set.forEach((cb) => cb(propName, value, oldValue));
102
139
  }
103
140
  };
104
- const state = (typeof Proxy === 'undefined'
105
- ? {}
106
- : new Proxy(unwrappedState, {
141
+ const state = (proxyAvailable
142
+ ? new Proxy(initialState, {
107
143
  get(_, propName) {
108
144
  return get(propName);
109
145
  },
@@ -123,7 +159,11 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
123
159
  set(propName, value);
124
160
  return true;
125
161
  },
126
- }));
162
+ })
163
+ : (() => {
164
+ syncPlainStateKeys();
165
+ return plainState;
166
+ })());
127
167
  const on = (eventName, callback) => {
128
168
  handlers[eventName].push(callback);
129
169
  return () => {
@@ -136,7 +176,10 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
136
176
  cb(newValue);
137
177
  }
138
178
  };
139
- const resetHandler = () => cb(unwrap(defaultState)[propName]);
179
+ const resetHandler = () => {
180
+ const snapshot = resolveDefaultState();
181
+ cb(snapshot[propName]);
182
+ };
140
183
  // Register the handlers
141
184
  const unSet = on('set', setHandler);
142
185
  const unReset = on('reset', resetHandler);
@@ -179,6 +222,38 @@ const createObservableMap = (defaultState, shouldUpdate = (a, b) => a !== b) =>
179
222
  changeListeners.delete(listener);
180
223
  }
181
224
  };
225
+ function ensurePlainProperty(key) {
226
+ if (proxyAvailable || !plainState) {
227
+ return;
228
+ }
229
+ if (Object.prototype.hasOwnProperty.call(plainState, key)) {
230
+ return;
231
+ }
232
+ Object.defineProperty(plainState, key, {
233
+ configurable: true,
234
+ enumerable: true,
235
+ get() {
236
+ return get(key);
237
+ },
238
+ set(value) {
239
+ set(key, value);
240
+ },
241
+ });
242
+ }
243
+ function syncPlainStateKeys() {
244
+ if (proxyAvailable || !plainState) {
245
+ return;
246
+ }
247
+ const knownKeys = new Set(states.keys());
248
+ for (const key of Object.keys(plainState)) {
249
+ if (!knownKeys.has(key)) {
250
+ delete plainState[key];
251
+ }
252
+ }
253
+ for (const key of knownKeys) {
254
+ ensurePlainProperty(key);
255
+ }
256
+ }
182
257
  return {
183
258
  state,
184
259
  get,
@@ -1,2 +1,2 @@
1
- export declare const appendToMap: <K, V>(map: Map<K, V[]>, propName: K, value: V) => void;
1
+ export declare const appendToMap: <K, V extends Object>(map: Map<K, Set<WeakRef<V>>>, refsByValue: WeakMap<V, WeakRef<V>>, propName: K, value: V) => void;
2
2
  export declare const debounce: <T extends (...args: any[]) => any>(fn: T, ms: number) => ((...args: Parameters<T>) => void);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stencil/store",
3
3
  "author": "StencilJS Team",
4
- "version": "2.2.1",
4
+ "version": "2.2.3-dev.1785970285.b07d6c8",
5
5
  "description": "Store is a lightweight shared state library by the StencilJS core team. Implements a simple key/value map that efficiently re-renders components when necessary.",
6
6
  "license": "MIT",
7
7
  "homepage": "https://stenciljs.com/docs/stencil-store",
@@ -33,11 +33,11 @@
33
33
  "npm": ">=6.0.0"
34
34
  },
35
35
  "scripts": {
36
- "build": "run-s build.*",
37
- "build.clean": "rm -rf dist",
36
+ "build": "run-s build.clean build.rollup",
37
+ "build.clean": "rimraf dist",
38
38
  "build.rollup": "rollup -c rollup.config.js",
39
39
  "prettier": "npm run prettier.base -- --write",
40
- "prettier.base": "prettier --cache 'src/**/*.ts'",
40
+ "prettier.base": "prettier --cache \"src/**/*.ts\"",
41
41
  "prettier.dry-run": "npm run prettier.base -- --list-different",
42
42
  "release": "np",
43
43
  "test": "run-s test.*",
@@ -53,16 +53,17 @@
53
53
  },
54
54
  "devDependencies": {
55
55
  "@ionic/prettier-config": "^4.0.0",
56
- "@rollup/plugin-typescript": "^12.1.2",
57
- "@stencil/core": "^4.27.1",
58
- "@types/node": "^24.0.3",
59
- "@vitest/coverage-v8": "^3.0.7",
60
- "np": "^10.2.0",
61
- "npm-run-all2": "^8.0.1",
62
- "prettier": "^3.5.2",
63
- "rollup": "^4.34.8",
64
- "typescript": "~5.9.2",
65
- "vitest": "^3.0.7"
56
+ "@rollup/plugin-typescript": "^12.3.0",
57
+ "@stencil/core": "^4.38.2",
58
+ "@types/node": "^26.0.0",
59
+ "@vitest/coverage-v8": "^4.0.5",
60
+ "np": "^11.0.1",
61
+ "npm-run-all2": "^9.0.1",
62
+ "prettier": "^3.6.2",
63
+ "rimraf": "^6.0.1",
64
+ "rollup": "^4.52.5",
65
+ "typescript": "~6.0.2",
66
+ "vitest": "^4.0.5"
66
67
  },
67
68
  "prettier": "@ionic/prettier-config"
68
69
  }
File without changes
File without changes
File without changes