diff --git a/package.json b/package.json index 4bf8502..45fa67a 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "gulp-uglify": "^1.5.3", "knuth-shuffle": "^1.0.1", "testem": "^1.0.2", - "typescript": "^2.0.6", + "typescript": "^2.1.0", "xyz": "0.5.x" }, "scripts": { diff --git a/src/h.ts b/src/h.ts index ed42c14..6a35833 100644 --- a/src/h.ts +++ b/src/h.ts @@ -1,4 +1,4 @@ -import {vnode, VNode} from './vnode'; +import {vnode, VNode, VNodeData} from './vnode'; import * as is from './is'; function addNS(data: any, children: Array | undefined, sel: string | undefined): void { @@ -14,13 +14,13 @@ function addNS(data: any, children: Array | undefined, sel: string | unde } export function h(sel: string): VNode; -export function h(sel: string, data: any): VNode; +export function h(sel: string, data: VNodeData): VNode; export function h(sel: string, text: string): VNode; export function h(sel: string, children: Array): VNode; -export function h(sel: string, data: any, text: string): VNode; -export function h(sel: string, data: any, children: Array): VNode; +export function h(sel: string, data: VNodeData, text: string): VNode; +export function h(sel: string, data: VNodeData, children: Array): VNode; export function h(sel: any, b?: any, c?: any): VNode { - var data = {}, children: any, text: any, i: number; + var data: VNodeData = {}, children: any, text: any, i: number; if (c !== undefined) { data = b; if (is.array(c)) { children = c; } diff --git a/src/helpers/attachto.ts b/src/helpers/attachto.ts index bc08b91..0d42493 100755 --- a/src/helpers/attachto.ts +++ b/src/helpers/attachto.ts @@ -16,7 +16,9 @@ function post(_: any, vnode: VNode): void { function destroy(vnode: VNode): void { // Remove placeholder - vnode.elm && vnode.elm.parentNode && vnode.elm.parentNode.removeChild(vnode.elm); + if (vnode.elm !== undefined) { + (vnode.elm.parentNode as HTMLElement).removeChild(vnode.elm); + } // Remove real element from where it was inserted vnode.elm = (vnode.data as VNodeData).attachData.real; } @@ -44,4 +46,4 @@ export function attachTo(target: Element, vnode: VNode): VNode { hook.destroy = destroy; return vnode; }; -export default attachTo; \ No newline at end of file +export default attachTo; diff --git a/src/htmldomapi.ts b/src/htmldomapi.ts index 95d4e9e..6d6906b 100644 --- a/src/htmldomapi.ts +++ b/src/htmldomapi.ts @@ -63,4 +63,5 @@ export const htmlDomApi = { tagName, setTextContent, } as DOMAPI; -export default htmlDomApi; \ No newline at end of file + +export default htmlDomApi; diff --git a/src/modules/module.d.ts b/src/modules/module.d.ts index eab4951..256d8ba 100644 --- a/src/modules/module.d.ts +++ b/src/modules/module.d.ts @@ -1,10 +1,10 @@ import {PreHook, CreateHook, UpdateHook, DestroyHook, RemoveHook, PostHook} from '../hooks'; export interface Module { - pre?: PreHook; - create?: CreateHook; - update?: UpdateHook; - destroy?: DestroyHook; - remove?: RemoveHook; - post?: PostHook; + pre: PreHook; + create: CreateHook; + update: UpdateHook; + destroy: DestroyHook; + remove: RemoveHook; + post: PostHook; } \ No newline at end of file diff --git a/src/snabbdom.ts b/src/snabbdom.ts index 47b23f5..e89b66b 100644 --- a/src/snabbdom.ts +++ b/src/snabbdom.ts @@ -1,4 +1,5 @@ /* global module, document, Node */ +import {Module} from './modules/module'; import {Hooks} from './hooks'; import vnode, {VNode, VNodeData, Key} from './vnode'; import * as is from './is'; @@ -21,8 +22,14 @@ function isVnode(vnode: any): vnode is VNode { type KeyToIndexMap = {[key: string]: number}; +type ArraysOf = { + [K in keyof T]: (T[K])[]; +} + +type ModuleHooks = ArraysOf; + function createKeyToOldIdx(children: Array, beginIdx: number, endIdx: number): KeyToIndexMap { - let i: number, map: {[s: string]: number} = {}, key: Key; + let i: number, map: KeyToIndexMap = {}, key: Key; for (i = beginIdx; i <= endIdx; ++i) { key = children[i].key; if (key !== undefined) map[key] = i; @@ -30,20 +37,23 @@ function createKeyToOldIdx(children: Array, beginIdx: number, endIdx: num return map; } -const hooks = ['create', 'update', 'remove', 'destroy', 'pre', 'post']; +const hooks: (keyof Module)[] = ['create', 'update', 'remove', 'destroy', 'pre', 'post']; export {h} from './h'; export {thunk} from './thunk'; -export function init(modules: Array, domApi?: DOMAPI) { - let i: number, j: number, cbs: any = {}; +export function init(modules: Array>, domApi?: DOMAPI) { + let i: number, j: number, cbs = ({} as ModuleHooks); const api: DOMAPI = domApi !== undefined ? domApi : htmlDomApi; for (i = 0; i < hooks.length; ++i) { cbs[hooks[i]] = []; for (j = 0; j < modules.length; ++j) { - if ((modules[j] as any)[hooks[i]] !== undefined) cbs[hooks[i]].push((modules[j] as any)[hooks[i]]); + const hook = modules[j][hooks[i]]; + if (hook !== undefined) { + (cbs[hooks[i]] as Array).push(hook); + } } } @@ -225,26 +235,28 @@ export function init(modules: Array, domApi?: DOMAPI) { if (isDef(i = vnode.data) && isDef(hook = i.hook) && isDef(i = hook.prepatch)) { i(oldVnode, vnode); } - let elm = vnode.elm = oldVnode.elm, oldCh = oldVnode.children, ch = vnode.children; + const elm = vnode.elm = (oldVnode.elm as Node); + let oldCh = oldVnode.children; + let ch = vnode.children; if (oldVnode === vnode) return; - if (isDef(vnode.data)) { + if (vnode.data !== undefined) { for (i = 0; i < cbs.update.length; ++i) cbs.update[i](oldVnode, vnode); - i = (vnode.data as VNodeData).hook; + i = vnode.data.hook; if (isDef(i) && isDef(i = i.update)) i(oldVnode, vnode); } if (isUndef(vnode.text)) { if (isDef(oldCh) && isDef(ch)) { - if (oldCh !== ch) updateChildren(elm as Node, oldCh as Array, ch as Array, insertedVnodeQueue); + if (oldCh !== ch) updateChildren(elm, oldCh as Array, ch as Array, insertedVnodeQueue); } else if (isDef(ch)) { - if (isDef(oldVnode.text)) api.setTextContent(elm as Node, ''); - addVnodes(elm as Node, null, ch as Array, 0, (ch as Array).length - 1, insertedVnodeQueue); + if (isDef(oldVnode.text)) api.setTextContent(elm, ''); + addVnodes(elm, null, ch as Array, 0, (ch as Array).length - 1, insertedVnodeQueue); } else if (isDef(oldCh)) { - removeVnodes(elm as Node, oldCh as Array, 0, (oldCh as Array).length - 1); + removeVnodes(elm, oldCh as Array, 0, (oldCh as Array).length - 1); } else if (isDef(oldVnode.text)) { - api.setTextContent(elm as Node, ''); + api.setTextContent(elm, ''); } } else if (oldVnode.text !== vnode.text) { - api.setTextContent(elm as Node, vnode.text as string); + api.setTextContent(elm, vnode.text as string); } if (isDef(hook) && isDef(i = hook.postpatch)) { i(oldVnode, vnode); diff --git a/src/vnode.ts b/src/vnode.ts index d9055d8..ba7c962 100644 --- a/src/vnode.ts +++ b/src/vnode.ts @@ -1,6 +1,6 @@ import {Hooks} from './hooks'; -export type Key = string | number | undefined; +export type Key = string | number; export interface VNode { sel: string | undefined; @@ -21,13 +21,13 @@ export interface VNodeData { on?: any; hero?: any; attachData?: any; - [key: string]: any; // for any other 3rd party module - // end of modules hook?: Hooks; - key?: string | number; + key?: Key; ns?: string; // for SVGs fn?: () => VNode; // for thunks args?: Array; // for thunks + [key: string]: any; // for any other 3rd party module + // end of modules } export function vnode(sel: string,