isomorfeus-preact 10.6.12 → 10.6.16

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