isomorfeus-preact 10.8.1 → 10.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/lib/preact/version.rb +1 -1
  3. data/node_modules/.package-lock.json +5 -7
  4. data/node_modules/preact/compat/dist/compat.js +2 -2
  5. data/node_modules/preact/compat/dist/compat.js.map +1 -1
  6. data/node_modules/preact/compat/dist/compat.mjs +2 -2
  7. data/node_modules/preact/compat/dist/compat.module.js +2 -2
  8. data/node_modules/preact/compat/dist/compat.module.js.map +1 -1
  9. data/node_modules/preact/compat/dist/compat.umd.js +2 -2
  10. data/node_modules/preact/compat/dist/compat.umd.js.map +1 -1
  11. data/node_modules/preact/compat/src/render.js +238 -238
  12. data/node_modules/preact/debug/dist/debug.js +2 -2
  13. data/node_modules/preact/debug/dist/debug.js.map +1 -1
  14. data/node_modules/preact/debug/dist/debug.mjs +2 -2
  15. data/node_modules/preact/debug/dist/debug.module.js +2 -2
  16. data/node_modules/preact/debug/dist/debug.module.js.map +1 -1
  17. data/node_modules/preact/debug/dist/debug.umd.js +2 -2
  18. data/node_modules/preact/debug/dist/debug.umd.js.map +1 -1
  19. data/node_modules/preact/debug/src/debug.js +437 -444
  20. data/node_modules/preact/devtools/dist/devtools.js +2 -2
  21. data/node_modules/preact/devtools/dist/devtools.js.map +1 -1
  22. data/node_modules/preact/devtools/dist/devtools.mjs +2 -2
  23. data/node_modules/preact/devtools/dist/devtools.module.js +2 -2
  24. data/node_modules/preact/devtools/dist/devtools.module.js.map +1 -1
  25. data/node_modules/preact/devtools/dist/devtools.umd.js +2 -2
  26. data/node_modules/preact/devtools/dist/devtools.umd.js.map +1 -1
  27. data/node_modules/preact/devtools/src/devtools.js +10 -10
  28. data/node_modules/preact/hooks/dist/hooks.js +2 -2
  29. data/node_modules/preact/hooks/dist/hooks.js.map +1 -1
  30. data/node_modules/preact/hooks/dist/hooks.mjs +2 -2
  31. data/node_modules/preact/hooks/dist/hooks.module.js +2 -2
  32. data/node_modules/preact/hooks/dist/hooks.module.js.map +1 -1
  33. data/node_modules/preact/hooks/dist/hooks.umd.js +2 -2
  34. data/node_modules/preact/hooks/dist/hooks.umd.js.map +1 -1
  35. data/node_modules/preact/hooks/src/index.js +417 -426
  36. data/node_modules/preact/package.json +304 -304
  37. data/package.json +1 -1
  38. metadata +4 -4
@@ -1,426 +1,417 @@
1
- import { options } from 'preact';
2
-
3
- /** @type {number} */
4
- let currentIndex;
5
-
6
- /** @type {import('./internal').Component} */
7
- let currentComponent;
8
-
9
- /** @type {import('./internal').Component} */
10
- let previousComponent;
11
-
12
- /** @type {number} */
13
- let currentHook = 0;
14
-
15
- /** @type {Array<import('./internal').Component>} */
16
- let afterPaintEffects = [];
17
-
18
- let oldBeforeDiff = options._diff;
19
- let oldBeforeRender = options._render;
20
- let oldAfterDiff = options.diffed;
21
- let oldCommit = options._commit;
22
- let oldBeforeUnmount = options.unmount;
23
-
24
- const RAF_TIMEOUT = 100;
25
- let prevRaf;
26
-
27
- options._diff = vnode => {
28
- currentComponent = null;
29
- if (oldBeforeDiff) oldBeforeDiff(vnode);
30
- };
31
-
32
- options._render = vnode => {
33
- if (oldBeforeRender) oldBeforeRender(vnode);
34
-
35
- currentComponent = vnode._component;
36
- currentIndex = 0;
37
-
38
- const hooks = currentComponent.__hooks;
39
- if (hooks) {
40
- if (previousComponent === currentComponent) {
41
- hooks._pendingEffects = [];
42
- currentComponent._renderCallbacks = [];
43
- hooks._list.forEach(hookItem => {
44
- hookItem._pendingValue = hookItem._pendingArgs = undefined;
45
- });
46
- } else {
47
- hooks._list.forEach(hookItem => {
48
- if (hookItem._pendingArgs) {
49
- hookItem._args = hookItem._pendingArgs;
50
- }
51
- if (hookItem._pendingValue) {
52
- hookItem._value = hookItem._pendingValue;
53
- }
54
- hookItem._pendingValue = hookItem._pendingArgs = undefined;
55
- });
56
- hooks._pendingEffects.forEach(invokeCleanup);
57
- hooks._pendingEffects.forEach(invokeEffect);
58
- hooks._pendingEffects = [];
59
- }
60
- }
61
- previousComponent = currentComponent;
62
- };
63
-
64
- options.diffed = vnode => {
65
- if (oldAfterDiff) oldAfterDiff(vnode);
66
-
67
- const c = vnode._component;
68
- if (c && c.__hooks && c.__hooks._pendingEffects.length) {
69
- afterPaint(afterPaintEffects.push(c));
70
- }
71
- currentComponent = null;
72
- previousComponent = null;
73
- };
74
-
75
- options._commit = (vnode, commitQueue) => {
76
- commitQueue.some(component => {
77
- try {
78
- if (component.__hooks) {
79
- component.__hooks._list.forEach(hookItem => {
80
- if (hookItem._pendingArgs) {
81
- hookItem._args = hookItem._pendingArgs;
82
- }
83
- if (hookItem._pendingValue) {
84
- hookItem._value = hookItem._pendingValue;
85
- }
86
- hookItem._pendingValue = hookItem._pendingArgs = undefined;
87
- });
88
- }
89
-
90
- component._renderCallbacks.forEach(invokeCleanup);
91
- component._renderCallbacks = component._renderCallbacks.filter(cb =>
92
- cb._value ? invokeEffect(cb) : true
93
- );
94
- } catch (e) {
95
- commitQueue.some(c => {
96
- if (c._renderCallbacks) c._renderCallbacks = [];
97
- });
98
- commitQueue = [];
99
- options._catchError(e, component._vnode);
100
- }
101
- });
102
-
103
- if (oldCommit) oldCommit(vnode, commitQueue);
104
- };
105
-
106
- options.unmount = vnode => {
107
- if (oldBeforeUnmount) oldBeforeUnmount(vnode);
108
-
109
- const c = vnode._component;
110
- if (c && c.__hooks) {
111
- let hasErrored;
112
- c.__hooks._list.forEach(s => {
113
- try {
114
- invokeCleanup(s);
115
- } catch (e) {
116
- hasErrored = e;
117
- }
118
- });
119
- if (hasErrored) options._catchError(hasErrored, c._vnode);
120
- }
121
- };
122
-
123
- /**
124
- * Get a hook's state from the currentComponent
125
- * @param {number} index The index of the hook to get
126
- * @param {number} type The index of the hook to get
127
- * @returns {any}
128
- */
129
- function getHookState(index, type) {
130
- if (options._hook) {
131
- options._hook(currentComponent, index, currentHook || type);
132
- }
133
- currentHook = 0;
134
-
135
- // Largely inspired by:
136
- // * https://github.com/michael-klein/funcy.js/blob/f6be73468e6ec46b0ff5aa3cc4c9baf72a29025a/src/hooks/core_hooks.mjs
137
- // * https://github.com/michael-klein/funcy.js/blob/650beaa58c43c33a74820a3c98b3c7079cf2e333/src/renderer.mjs
138
- // Other implementations to look at:
139
- // * https://codesandbox.io/s/mnox05qp8
140
- const hooks =
141
- currentComponent.__hooks ||
142
- (currentComponent.__hooks = {
143
- _list: [],
144
- _pendingEffects: []
145
- });
146
-
147
- if (index >= hooks._list.length) {
148
- hooks._list.push({});
149
- }
150
- return hooks._list[index];
151
- }
152
-
153
- /**
154
- * @param {import('./index').StateUpdater<any>} [initialState]
155
- */
156
- export function useState(initialState) {
157
- currentHook = 1;
158
- return useReducer(invokeOrReturn, initialState);
159
- }
160
-
161
- /**
162
- * @param {import('./index').Reducer<any, any>} reducer
163
- * @param {import('./index').StateUpdater<any>} initialState
164
- * @param {(initialState: any) => void} [init]
165
- * @returns {[ any, (state: any) => void ]}
166
- */
167
- export function useReducer(reducer, initialState, init) {
168
- /** @type {import('./internal').ReducerHookState} */
169
- const hookState = getHookState(currentIndex++, 2);
170
- hookState._reducer = reducer;
171
- if (!hookState._component) {
172
- hookState._value = [
173
- !init ? invokeOrReturn(undefined, initialState) : init(initialState),
174
-
175
- action => {
176
- const nextValue = hookState._reducer(hookState._value[0], action);
177
- if (hookState._value[0] !== nextValue) {
178
- hookState._value = [nextValue, hookState._value[1]];
179
- hookState._component.setState({});
180
- }
181
- }
182
- ];
183
-
184
- hookState._component = currentComponent;
185
- }
186
-
187
- return hookState._value;
188
- }
189
-
190
- /**
191
- * @param {import('./internal').Effect} callback
192
- * @param {any[]} args
193
- */
194
- export function useEffect(callback, args) {
195
- /** @type {import('./internal').EffectHookState} */
196
- const state = getHookState(currentIndex++, 3);
197
- if (!options._skipEffects && argsChanged(state._args, args)) {
198
- state._value = callback;
199
- state._pendingArgs = args;
200
-
201
- currentComponent.__hooks._pendingEffects.push(state);
202
- }
203
- }
204
-
205
- /**
206
- * @param {import('./internal').Effect} callback
207
- * @param {any[]} args
208
- */
209
- export function useLayoutEffect(callback, args) {
210
- /** @type {import('./internal').EffectHookState} */
211
- const state = getHookState(currentIndex++, 4);
212
- if (!options._skipEffects && argsChanged(state._args, args)) {
213
- state._value = callback;
214
- state._pendingArgs = args;
215
-
216
- currentComponent._renderCallbacks.push(state);
217
- }
218
- }
219
-
220
- export function useRef(initialValue) {
221
- currentHook = 5;
222
- return useMemo(() => ({ current: initialValue }), []);
223
- }
224
-
225
- /**
226
- * @param {object} ref
227
- * @param {() => object} createHandle
228
- * @param {any[]} args
229
- */
230
- export function useImperativeHandle(ref, createHandle, args) {
231
- currentHook = 6;
232
- useLayoutEffect(
233
- () => {
234
- if (typeof ref == 'function') {
235
- ref(createHandle());
236
- return () => ref(null);
237
- } else if (ref) {
238
- ref.current = createHandle();
239
- return () => (ref.current = null);
240
- }
241
- },
242
- args == null ? args : args.concat(ref)
243
- );
244
- }
245
-
246
- /**
247
- * @param {() => any} factory
248
- * @param {any[]} args
249
- */
250
- export function useMemo(factory, args) {
251
- /** @type {import('./internal').MemoHookState} */
252
- const state = getHookState(currentIndex++, 7);
253
- if (argsChanged(state._args, args)) {
254
- state._pendingValue = factory();
255
- state._pendingArgs = args;
256
- state._factory = factory;
257
- return state._pendingValue;
258
- }
259
-
260
- return state._value;
261
- }
262
-
263
- /**
264
- * @param {() => void} callback
265
- * @param {any[]} args
266
- */
267
- export function useCallback(callback, args) {
268
- currentHook = 8;
269
- return useMemo(() => callback, args);
270
- }
271
-
272
- /**
273
- * @param {import('./internal').PreactContext} context
274
- */
275
- export function useContext(context) {
276
- const provider = currentComponent.context[context._id];
277
- // We could skip this call here, but than we'd not call
278
- // `options._hook`. We need to do that in order to make
279
- // the devtools aware of this hook.
280
- /** @type {import('./internal').ContextHookState} */
281
- const state = getHookState(currentIndex++, 9);
282
- // The devtools needs access to the context object to
283
- // be able to pull of the default value when no provider
284
- // is present in the tree.
285
- state._context = context;
286
- if (!provider) return context._defaultValue;
287
- // This is probably not safe to convert to "!"
288
- if (state._value == null) {
289
- state._value = true;
290
- provider.sub(currentComponent);
291
- }
292
- return provider.props.value;
293
- }
294
-
295
- /**
296
- * Display a custom label for a custom hook for the devtools panel
297
- * @type {<T>(value: T, cb?: (value: T) => string | number) => void}
298
- */
299
- export function useDebugValue(value, formatter) {
300
- if (options.useDebugValue) {
301
- options.useDebugValue(formatter ? formatter(value) : value);
302
- }
303
- }
304
-
305
- /**
306
- * @param {(error: any) => void} cb
307
- */
308
- export function useErrorBoundary(cb) {
309
- /** @type {import('./internal').ErrorBoundaryHookState} */
310
- const state = getHookState(currentIndex++, 10);
311
- const errState = useState();
312
- state._value = cb;
313
- if (!currentComponent.componentDidCatch) {
314
- currentComponent.componentDidCatch = err => {
315
- if (state._value) state._value(err);
316
- errState[1](err);
317
- };
318
- }
319
- return [
320
- errState[0],
321
- () => {
322
- errState[1](undefined);
323
- }
324
- ];
325
- }
326
-
327
- /**
328
- * After paint effects consumer.
329
- */
330
- function flushAfterPaintEffects() {
331
- let component;
332
- while ((component = afterPaintEffects.shift())) {
333
- if (!component._parentDom) continue;
334
- try {
335
- component.__hooks._pendingEffects.forEach(invokeCleanup);
336
- component.__hooks._pendingEffects.forEach(invokeEffect);
337
- component.__hooks._pendingEffects = [];
338
- } catch (e) {
339
- component.__hooks._pendingEffects = [];
340
- options._catchError(e, component._vnode);
341
- }
342
- }
343
- }
344
-
345
- let HAS_RAF = typeof requestAnimationFrame == 'function';
346
-
347
- /**
348
- * Schedule a callback to be invoked after the browser has a chance to paint a new frame.
349
- * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after
350
- * the next browser frame.
351
- *
352
- * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked
353
- * even if RAF doesn't fire (for example if the browser tab is not visible)
354
- *
355
- * @param {() => void} callback
356
- */
357
- function afterNextFrame(callback) {
358
- const done = () => {
359
- clearTimeout(timeout);
360
- if (HAS_RAF) cancelAnimationFrame(raf);
361
- setTimeout(callback);
362
- };
363
- const timeout = setTimeout(done, RAF_TIMEOUT);
364
-
365
- let raf;
366
- if (HAS_RAF) {
367
- raf = requestAnimationFrame(done);
368
- }
369
- }
370
-
371
- // Note: if someone used options.debounceRendering = requestAnimationFrame,
372
- // then effects will ALWAYS run on the NEXT frame instead of the current one, incurring a ~16ms delay.
373
- // Perhaps this is not such a big deal.
374
- /**
375
- * Schedule afterPaintEffects flush after the browser paints
376
- * @param {number} newQueueLength
377
- */
378
- function afterPaint(newQueueLength) {
379
- if (newQueueLength === 1 || prevRaf !== options.requestAnimationFrame) {
380
- prevRaf = options.requestAnimationFrame;
381
- (prevRaf || afterNextFrame)(flushAfterPaintEffects);
382
- }
383
- }
384
-
385
- /**
386
- * @param {import('./internal').EffectHookState} hook
387
- */
388
- function invokeCleanup(hook) {
389
- // A hook cleanup can introduce a call to render which creates a new root, this will call options.vnode
390
- // and move the currentComponent away.
391
- const comp = currentComponent;
392
- let cleanup = hook._cleanup;
393
- if (typeof cleanup == 'function') {
394
- hook._cleanup = undefined;
395
- cleanup();
396
- }
397
- currentComponent = comp;
398
- }
399
-
400
- /**
401
- * Invoke a Hook's effect
402
- * @param {import('./internal').EffectHookState} hook
403
- */
404
- function invokeEffect(hook) {
405
- // A hook call can introduce a call to render which creates a new root, this will call options.vnode
406
- // and move the currentComponent away.
407
- const comp = currentComponent;
408
- hook._cleanup = hook._value();
409
- currentComponent = comp;
410
- }
411
-
412
- /**
413
- * @param {any[]} oldArgs
414
- * @param {any[]} newArgs
415
- */
416
- function argsChanged(oldArgs, newArgs) {
417
- return (
418
- !oldArgs ||
419
- oldArgs.length !== newArgs.length ||
420
- newArgs.some((arg, index) => arg !== oldArgs[index])
421
- );
422
- }
423
-
424
- function invokeOrReturn(arg, f) {
425
- return typeof f == 'function' ? f(arg) : f;
426
- }
1
+ import { options } from 'preact';
2
+
3
+ /** @type {number} */
4
+ let currentIndex;
5
+
6
+ /** @type {import('./internal').Component} */
7
+ let currentComponent;
8
+
9
+ /** @type {import('./internal').Component} */
10
+ let previousComponent;
11
+
12
+ /** @type {number} */
13
+ let currentHook = 0;
14
+
15
+ /** @type {Array<import('./internal').Component>} */
16
+ let afterPaintEffects = [];
17
+
18
+ let EMPTY = [];
19
+
20
+ let oldBeforeDiff = options._diff;
21
+ let oldBeforeRender = options._render;
22
+ let oldAfterDiff = options.diffed;
23
+ let oldCommit = options._commit;
24
+ let oldBeforeUnmount = options.unmount;
25
+
26
+ const RAF_TIMEOUT = 100;
27
+ let prevRaf;
28
+
29
+ options._diff = vnode => {
30
+ currentComponent = null;
31
+ if (oldBeforeDiff) oldBeforeDiff(vnode);
32
+ };
33
+
34
+ options._render = vnode => {
35
+ if (oldBeforeRender) oldBeforeRender(vnode);
36
+
37
+ currentComponent = vnode._component;
38
+ currentIndex = 0;
39
+
40
+ const hooks = currentComponent.__hooks;
41
+ if (hooks) {
42
+ if (previousComponent === currentComponent) {
43
+ hooks._pendingEffects = [];
44
+ currentComponent._renderCallbacks = [];
45
+ hooks._list.forEach(hookItem => {
46
+ hookItem._pendingValue = EMPTY;
47
+ hookItem._pendingArgs = undefined;
48
+ });
49
+ } else {
50
+ hooks._pendingEffects.forEach(invokeCleanup);
51
+ hooks._pendingEffects.forEach(invokeEffect);
52
+ hooks._pendingEffects = [];
53
+ }
54
+ }
55
+ previousComponent = currentComponent;
56
+ };
57
+
58
+ options.diffed = vnode => {
59
+ if (oldAfterDiff) oldAfterDiff(vnode);
60
+
61
+ const c = vnode._component;
62
+ if (c && c.__hooks) {
63
+ if (c.__hooks._pendingEffects.length) afterPaint(afterPaintEffects.push(c));
64
+ c.__hooks._list.forEach(hookItem => {
65
+ if (hookItem._pendingArgs) {
66
+ hookItem._args = hookItem._pendingArgs;
67
+ }
68
+ if (hookItem._pendingValue !== EMPTY) {
69
+ hookItem._value = hookItem._pendingValue;
70
+ }
71
+ hookItem._pendingArgs = undefined;
72
+ hookItem._pendingValue = EMPTY;
73
+ });
74
+ }
75
+ previousComponent = currentComponent = null;
76
+ };
77
+
78
+ options._commit = (vnode, commitQueue) => {
79
+ commitQueue.some(component => {
80
+ try {
81
+ component._renderCallbacks.forEach(invokeCleanup);
82
+ component._renderCallbacks = component._renderCallbacks.filter(cb =>
83
+ cb._value ? invokeEffect(cb) : true
84
+ );
85
+ } catch (e) {
86
+ commitQueue.some(c => {
87
+ if (c._renderCallbacks) c._renderCallbacks = [];
88
+ });
89
+ commitQueue = [];
90
+ options._catchError(e, component._vnode);
91
+ }
92
+ });
93
+
94
+ if (oldCommit) oldCommit(vnode, commitQueue);
95
+ };
96
+
97
+ options.unmount = vnode => {
98
+ if (oldBeforeUnmount) oldBeforeUnmount(vnode);
99
+
100
+ const c = vnode._component;
101
+ if (c && c.__hooks) {
102
+ let hasErrored;
103
+ c.__hooks._list.forEach(s => {
104
+ try {
105
+ invokeCleanup(s);
106
+ } catch (e) {
107
+ hasErrored = e;
108
+ }
109
+ });
110
+ if (hasErrored) options._catchError(hasErrored, c._vnode);
111
+ }
112
+ };
113
+
114
+ /**
115
+ * Get a hook's state from the currentComponent
116
+ * @param {number} index The index of the hook to get
117
+ * @param {number} type The index of the hook to get
118
+ * @returns {any}
119
+ */
120
+ function getHookState(index, type) {
121
+ if (options._hook) {
122
+ options._hook(currentComponent, index, currentHook || type);
123
+ }
124
+ currentHook = 0;
125
+
126
+ // Largely inspired by:
127
+ // * https://github.com/michael-klein/funcy.js/blob/f6be73468e6ec46b0ff5aa3cc4c9baf72a29025a/src/hooks/core_hooks.mjs
128
+ // * https://github.com/michael-klein/funcy.js/blob/650beaa58c43c33a74820a3c98b3c7079cf2e333/src/renderer.mjs
129
+ // Other implementations to look at:
130
+ // * https://codesandbox.io/s/mnox05qp8
131
+ const hooks =
132
+ currentComponent.__hooks ||
133
+ (currentComponent.__hooks = {
134
+ _list: [],
135
+ _pendingEffects: []
136
+ });
137
+
138
+ if (index >= hooks._list.length) {
139
+ hooks._list.push({ _pendingValue: EMPTY });
140
+ }
141
+ return hooks._list[index];
142
+ }
143
+
144
+ /**
145
+ * @param {import('./index').StateUpdater<any>} [initialState]
146
+ */
147
+ export function useState(initialState) {
148
+ currentHook = 1;
149
+ return useReducer(invokeOrReturn, initialState);
150
+ }
151
+
152
+ /**
153
+ * @param {import('./index').Reducer<any, any>} reducer
154
+ * @param {import('./index').StateUpdater<any>} initialState
155
+ * @param {(initialState: any) => void} [init]
156
+ * @returns {[ any, (state: any) => void ]}
157
+ */
158
+ export function useReducer(reducer, initialState, init) {
159
+ /** @type {import('./internal').ReducerHookState} */
160
+ const hookState = getHookState(currentIndex++, 2);
161
+ hookState._reducer = reducer;
162
+ if (!hookState._component) {
163
+ hookState._value = [
164
+ !init ? invokeOrReturn(undefined, initialState) : init(initialState),
165
+
166
+ action => {
167
+ const nextValue = hookState._reducer(hookState._value[0], action);
168
+ if (hookState._value[0] !== nextValue) {
169
+ hookState._value = [nextValue, hookState._value[1]];
170
+ hookState._component.setState({});
171
+ }
172
+ }
173
+ ];
174
+
175
+ hookState._component = currentComponent;
176
+ }
177
+
178
+ return hookState._value;
179
+ }
180
+
181
+ /**
182
+ * @param {import('./internal').Effect} callback
183
+ * @param {any[]} args
184
+ */
185
+ export function useEffect(callback, args) {
186
+ /** @type {import('./internal').EffectHookState} */
187
+ const state = getHookState(currentIndex++, 3);
188
+ if (!options._skipEffects && argsChanged(state._args, args)) {
189
+ state._value = callback;
190
+ state._pendingArgs = args;
191
+
192
+ currentComponent.__hooks._pendingEffects.push(state);
193
+ }
194
+ }
195
+
196
+ /**
197
+ * @param {import('./internal').Effect} callback
198
+ * @param {any[]} args
199
+ */
200
+ export function useLayoutEffect(callback, args) {
201
+ /** @type {import('./internal').EffectHookState} */
202
+ const state = getHookState(currentIndex++, 4);
203
+ if (!options._skipEffects && argsChanged(state._args, args)) {
204
+ state._value = callback;
205
+ state._pendingArgs = args;
206
+
207
+ currentComponent._renderCallbacks.push(state);
208
+ }
209
+ }
210
+
211
+ export function useRef(initialValue) {
212
+ currentHook = 5;
213
+ return useMemo(() => ({ current: initialValue }), []);
214
+ }
215
+
216
+ /**
217
+ * @param {object} ref
218
+ * @param {() => object} createHandle
219
+ * @param {any[]} args
220
+ */
221
+ export function useImperativeHandle(ref, createHandle, args) {
222
+ currentHook = 6;
223
+ useLayoutEffect(
224
+ () => {
225
+ if (typeof ref == 'function') {
226
+ ref(createHandle());
227
+ return () => ref(null);
228
+ } else if (ref) {
229
+ ref.current = createHandle();
230
+ return () => (ref.current = null);
231
+ }
232
+ },
233
+ args == null ? args : args.concat(ref)
234
+ );
235
+ }
236
+
237
+ /**
238
+ * @param {() => any} factory
239
+ * @param {any[]} args
240
+ */
241
+ export function useMemo(factory, args) {
242
+ /** @type {import('./internal').MemoHookState} */
243
+ const state = getHookState(currentIndex++, 7);
244
+ if (argsChanged(state._args, args)) {
245
+ state._pendingValue = factory();
246
+ state._pendingArgs = args;
247
+ state._factory = factory;
248
+ return state._pendingValue;
249
+ }
250
+
251
+ return state._value;
252
+ }
253
+
254
+ /**
255
+ * @param {() => void} callback
256
+ * @param {any[]} args
257
+ */
258
+ export function useCallback(callback, args) {
259
+ currentHook = 8;
260
+ return useMemo(() => callback, args);
261
+ }
262
+
263
+ /**
264
+ * @param {import('./internal').PreactContext} context
265
+ */
266
+ export function useContext(context) {
267
+ const provider = currentComponent.context[context._id];
268
+ // We could skip this call here, but than we'd not call
269
+ // `options._hook`. We need to do that in order to make
270
+ // the devtools aware of this hook.
271
+ /** @type {import('./internal').ContextHookState} */
272
+ const state = getHookState(currentIndex++, 9);
273
+ // The devtools needs access to the context object to
274
+ // be able to pull of the default value when no provider
275
+ // is present in the tree.
276
+ state._context = context;
277
+ if (!provider) return context._defaultValue;
278
+ // This is probably not safe to convert to "!"
279
+ if (state._value == null) {
280
+ state._value = true;
281
+ provider.sub(currentComponent);
282
+ }
283
+ return provider.props.value;
284
+ }
285
+
286
+ /**
287
+ * Display a custom label for a custom hook for the devtools panel
288
+ * @type {<T>(value: T, cb?: (value: T) => string | number) => void}
289
+ */
290
+ export function useDebugValue(value, formatter) {
291
+ if (options.useDebugValue) {
292
+ options.useDebugValue(formatter ? formatter(value) : value);
293
+ }
294
+ }
295
+
296
+ /**
297
+ * @param {(error: any) => void} cb
298
+ */
299
+ export function useErrorBoundary(cb) {
300
+ /** @type {import('./internal').ErrorBoundaryHookState} */
301
+ const state = getHookState(currentIndex++, 10);
302
+ const errState = useState();
303
+ state._value = cb;
304
+ if (!currentComponent.componentDidCatch) {
305
+ currentComponent.componentDidCatch = err => {
306
+ if (state._value) state._value(err);
307
+ errState[1](err);
308
+ };
309
+ }
310
+ return [
311
+ errState[0],
312
+ () => {
313
+ errState[1](undefined);
314
+ }
315
+ ];
316
+ }
317
+
318
+ /**
319
+ * After paint effects consumer.
320
+ */
321
+ function flushAfterPaintEffects() {
322
+ let component;
323
+ while ((component = afterPaintEffects.shift())) {
324
+ if (!component._parentDom) continue;
325
+ try {
326
+ component.__hooks._pendingEffects.forEach(invokeCleanup);
327
+ component.__hooks._pendingEffects.forEach(invokeEffect);
328
+ component.__hooks._pendingEffects = [];
329
+ } catch (e) {
330
+ component.__hooks._pendingEffects = [];
331
+ options._catchError(e, component._vnode);
332
+ }
333
+ }
334
+ }
335
+
336
+ let HAS_RAF = typeof requestAnimationFrame == 'function';
337
+
338
+ /**
339
+ * Schedule a callback to be invoked after the browser has a chance to paint a new frame.
340
+ * Do this by combining requestAnimationFrame (rAF) + setTimeout to invoke a callback after
341
+ * the next browser frame.
342
+ *
343
+ * Also, schedule a timeout in parallel to the the rAF to ensure the callback is invoked
344
+ * even if RAF doesn't fire (for example if the browser tab is not visible)
345
+ *
346
+ * @param {() => void} callback
347
+ */
348
+ function afterNextFrame(callback) {
349
+ const done = () => {
350
+ clearTimeout(timeout);
351
+ if (HAS_RAF) cancelAnimationFrame(raf);
352
+ setTimeout(callback);
353
+ };
354
+ const timeout = setTimeout(done, RAF_TIMEOUT);
355
+
356
+ let raf;
357
+ if (HAS_RAF) {
358
+ raf = requestAnimationFrame(done);
359
+ }
360
+ }
361
+
362
+ // Note: if someone used options.debounceRendering = requestAnimationFrame,
363
+ // then effects will ALWAYS run on the NEXT frame instead of the current one, incurring a ~16ms delay.
364
+ // Perhaps this is not such a big deal.
365
+ /**
366
+ * Schedule afterPaintEffects flush after the browser paints
367
+ * @param {number} newQueueLength
368
+ */
369
+ function afterPaint(newQueueLength) {
370
+ if (newQueueLength === 1 || prevRaf !== options.requestAnimationFrame) {
371
+ prevRaf = options.requestAnimationFrame;
372
+ (prevRaf || afterNextFrame)(flushAfterPaintEffects);
373
+ }
374
+ }
375
+
376
+ /**
377
+ * @param {import('./internal').EffectHookState} hook
378
+ */
379
+ function invokeCleanup(hook) {
380
+ // A hook cleanup can introduce a call to render which creates a new root, this will call options.vnode
381
+ // and move the currentComponent away.
382
+ const comp = currentComponent;
383
+ let cleanup = hook._cleanup;
384
+ if (typeof cleanup == 'function') {
385
+ hook._cleanup = undefined;
386
+ cleanup();
387
+ }
388
+ currentComponent = comp;
389
+ }
390
+
391
+ /**
392
+ * Invoke a Hook's effect
393
+ * @param {import('./internal').EffectHookState} hook
394
+ */
395
+ function invokeEffect(hook) {
396
+ // A hook call can introduce a call to render which creates a new root, this will call options.vnode
397
+ // and move the currentComponent away.
398
+ const comp = currentComponent;
399
+ hook._cleanup = hook._value();
400
+ currentComponent = comp;
401
+ }
402
+
403
+ /**
404
+ * @param {any[]} oldArgs
405
+ * @param {any[]} newArgs
406
+ */
407
+ function argsChanged(oldArgs, newArgs) {
408
+ return (
409
+ !oldArgs ||
410
+ oldArgs.length !== newArgs.length ||
411
+ newArgs.some((arg, index) => arg !== oldArgs[index])
412
+ );
413
+ }
414
+
415
+ function invokeOrReturn(arg, f) {
416
+ return typeof f == 'function' ? f(arg) : f;
417
+ }