1 | import { VNode, VNodeData } from "./vnode";
|
2 | import { h, addNS } from "./h";
|
3 |
|
4 | export interface ThunkData extends VNodeData {
|
5 | fn: () => VNode;
|
6 | args: any[];
|
7 | }
|
8 |
|
9 | export interface Thunk extends VNode {
|
10 | data: ThunkData;
|
11 | }
|
12 |
|
13 | export interface ThunkFn {
|
14 | (sel: string, fn: (...args: any[]) => any, args: any[]): Thunk;
|
15 | (sel: string, key: any, fn: (...args: any[]) => any, args: any[]): Thunk;
|
16 | }
|
17 |
|
18 | function copyToThunk(vnode: VNode, thunk: VNode): void {
|
19 | const ns = thunk.data?.ns;
|
20 | (vnode.data as VNodeData).fn = (thunk.data as VNodeData).fn;
|
21 | (vnode.data as VNodeData).args = (thunk.data as VNodeData).args;
|
22 | thunk.data = vnode.data;
|
23 | thunk.children = vnode.children;
|
24 | thunk.text = vnode.text;
|
25 | thunk.elm = vnode.elm;
|
26 | if (ns) addNS(thunk.data, thunk.children, thunk.sel);
|
27 | }
|
28 |
|
29 | function init(thunk: VNode): void {
|
30 | const cur = thunk.data as VNodeData;
|
31 | const vnode = (cur.fn as any)(...cur.args!);
|
32 | copyToThunk(vnode, thunk);
|
33 | }
|
34 |
|
35 | function prepatch(oldVnode: VNode, thunk: VNode): void {
|
36 | let i: number;
|
37 | const old = oldVnode.data as VNodeData;
|
38 | const cur = thunk.data as VNodeData;
|
39 | const oldArgs = old.args;
|
40 | const args = cur.args;
|
41 | if (old.fn !== cur.fn || (oldArgs as any).length !== (args as any).length) {
|
42 | copyToThunk((cur.fn as any)(...args!), thunk);
|
43 | return;
|
44 | }
|
45 | for (i = 0; i < (args as any).length; ++i) {
|
46 | if ((oldArgs as any)[i] !== (args as any)[i]) {
|
47 | copyToThunk((cur.fn as any)(...args!), thunk);
|
48 | return;
|
49 | }
|
50 | }
|
51 | copyToThunk(oldVnode, thunk);
|
52 | }
|
53 |
|
54 | export const thunk = function thunk(
|
55 | sel: string,
|
56 | key?: any,
|
57 | fn?: any,
|
58 | args?: any
|
59 | ): VNode {
|
60 | if (args === undefined) {
|
61 | args = fn;
|
62 | fn = key;
|
63 | key = undefined;
|
64 | }
|
65 | return h(sel, {
|
66 | key: key,
|
67 | hook: { init, prepatch },
|
68 | fn: fn,
|
69 | args: args,
|
70 | });
|
71 | } as ThunkFn;
|