diff --git a/.gitignore b/.gitignore index 7aa75b29f4..3d1322c33e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea .DS_Store .nyc_output node_modules diff --git a/package-lock.json b/package-lock.json index 28ecb0eedb..f87b3610df 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "svelte", - "version": "3.4.1", + "version": "3.4.2", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -4179,9 +4179,9 @@ "dev": true }, "typescript": { - "version": "3.2.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.2.4.tgz", - "integrity": "sha512-0RNDbSdEokBeEAkgNbxJ+BLwSManFy9TeXz8uW+48j/xhEXv1ePME60olyzw2XzUqUBNAYFeJadIqAgNqIACwg==", + "version": "3.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.4.5.tgz", + "integrity": "sha512-YycBxUb49UUhdNMU5aJ7z5Ej2XGmaIBL0x34vZ82fn3hGvD+bgrMrVDpatgz2f7YxUMJxMkbWxJZeAvDxVe7Vw==", "dev": true }, "uglify-js": { diff --git a/package.json b/package.json index 90ec6d27ec..b32e19786f 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "pretest": "npm run build", "posttest": "agadoo src/internal/index.js", "prepublishOnly": "export PUBLISH=true && npm run lint && npm test", - "tsd": "tsc -d src/store.ts --outDir ." + "tsd": "tsc -d src/store.ts --outDir .", + "typecheck": "tsc --noEmit" }, "repository": { "type": "git", @@ -84,7 +85,7 @@ "tiny-glob": "^0.2.1", "ts-node": "^8.0.2", "tslib": "^1.8.0", - "typescript": "^3.0.1" + "typescript": "^3.4.0" }, "nyc": { "include": [ diff --git a/src/compile/Component.ts b/src/compile/Component.ts index a429db41f6..a8145e6b2c 100644 --- a/src/compile/Component.ts +++ b/src/compile/Component.ts @@ -1,4 +1,5 @@ import MagicString, { Bundle } from 'magic-string'; +// @ts-ignore import { walk, childKeys } from 'estree-walker'; import { getLocator } from 'locate-character'; import Stats from '../Stats'; @@ -21,6 +22,7 @@ import { remove_indentation, add_indentation } from '../utils/indentation'; import get_object from './utils/get_object'; import unwrap_parens from './utils/unwrap_parens'; import Slot from './nodes/Slot'; +import { Node as ESTreeNode } from 'estree'; type ComponentOptions = { namespace?: string; @@ -758,7 +760,7 @@ export default class Component { }); } - if (is_reference(node, parent)) { + if (is_reference(node as ESTreeNode, parent as ESTreeNode)) { const object = get_object(node); const { name } = object; @@ -776,7 +778,7 @@ export default class Component { }); } - invalidate(name, value) { + invalidate(name, value?) { const variable = this.var_lookup.get(name); if (variable && (variable.subscribable && variable.reassigned)) { @@ -1022,7 +1024,7 @@ export default class Component { scope = map.get(node); } - if (is_reference(node, parent)) { + if (is_reference(node as ESTreeNode, parent as ESTreeNode)) { const { name } = flatten_reference(node); const owner = scope.find_owner(name); @@ -1113,7 +1115,7 @@ export default class Component { } else if (node.type === 'UpdateExpression') { const identifier = get_object(node.argument); assignees.add(identifier.name); - } else if (is_reference(node, parent)) { + } else if (is_reference(node as ESTreeNode, parent as ESTreeNode)) { const identifier = get_object(node); if (!assignee_nodes.has(identifier)) { const { name } = identifier; diff --git a/src/compile/index.ts b/src/compile/index.ts index e80a937932..526d8abaeb 100644 --- a/src/compile/index.ts +++ b/src/compile/index.ts @@ -55,7 +55,7 @@ function validate_options(options: CompileOptions, warnings: Warning[]) { } } -function get_name(filename) { +function get_name(filename: string) { if (!filename) return null; const parts = filename.split(/[\/\\]/); @@ -105,4 +105,4 @@ export default function compile(source: string, options: CompileOptions = {}) { : render_dom(component, options); return component.generate(js); -} \ No newline at end of file +} diff --git a/src/compile/nodes/Attribute.ts b/src/compile/nodes/Attribute.ts index c07960ce47..0b2d3a3700 100644 --- a/src/compile/nodes/Attribute.ts +++ b/src/compile/nodes/Attribute.ts @@ -67,6 +67,7 @@ export default class Attribute extends Node { this.should_cache = this.is_dynamic ? this.chunks.length === 1 + // @ts-ignore todo: probably error ? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name) : true : false; @@ -91,8 +92,10 @@ export default class Attribute extends Node { if (this.chunks.length === 0) return `""`; if (this.chunks.length === 1) { + return this.chunks[0].type === 'Text' - ? stringify(this.chunks[0].data) + ? stringify((this.chunks[0] as Text).data) + // @ts-ignore todo: probably error : this.chunks[0].render(block); } @@ -102,6 +105,7 @@ export default class Attribute extends Node { if (chunk.type === 'Text') { return stringify(chunk.data); } else { + // @ts-ignore todo: probably error return chunk.get_precedence() <= 13 ? `(${chunk.render()})` : chunk.render(); } }) @@ -114,7 +118,8 @@ export default class Attribute extends Node { return this.is_true ? true : this.chunks[0] - ? this.chunks[0].data + // method should be called only when `is_static = true` + ? (this.chunks[0] as Text).data : ''; } } diff --git a/src/compile/nodes/AwaitBlock.ts b/src/compile/nodes/AwaitBlock.ts index f8e6896b5d..cd57750d29 100644 --- a/src/compile/nodes/AwaitBlock.ts +++ b/src/compile/nodes/AwaitBlock.ts @@ -5,6 +5,7 @@ import CatchBlock from './CatchBlock'; import Expression from './shared/Expression'; export default class AwaitBlock extends Node { + type: 'AwaitBlock'; expression: Expression; value: string; error: string; diff --git a/src/compile/nodes/Binding.ts b/src/compile/nodes/Binding.ts index b03eba0c36..0d666a543f 100644 --- a/src/compile/nodes/Binding.ts +++ b/src/compile/nodes/Binding.ts @@ -5,6 +5,7 @@ import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; export default class Binding extends Node { + type: 'Binding'; name: string; expression: Expression; is_contextual: boolean; diff --git a/src/compile/nodes/CatchBlock.ts b/src/compile/nodes/CatchBlock.ts index 23c08a494c..0edc0f76d8 100644 --- a/src/compile/nodes/CatchBlock.ts +++ b/src/compile/nodes/CatchBlock.ts @@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; export default class CatchBlock extends AbstractBlock { + type: 'CatchBlock'; scope: TemplateScope; constructor(component, parent, scope, info) { diff --git a/src/compile/nodes/DebugTag.ts b/src/compile/nodes/DebugTag.ts index 4d2c3f6ae4..0fbfa592ad 100644 --- a/src/compile/nodes/DebugTag.ts +++ b/src/compile/nodes/DebugTag.ts @@ -2,6 +2,7 @@ import Node from './shared/Node'; import Expression from './shared/Expression'; export default class DebugTag extends Node { + type: 'DebugTag'; expressions: Expression[]; constructor(component, parent, scope, info) { @@ -11,4 +12,4 @@ export default class DebugTag extends Node { return new Expression(component, parent, scope, node); }); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/EachBlock.ts b/src/compile/nodes/EachBlock.ts index b58c023ac9..2f18373137 100644 --- a/src/compile/nodes/EachBlock.ts +++ b/src/compile/nodes/EachBlock.ts @@ -6,8 +6,15 @@ import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; import { Node as INode } from '../../interfaces'; import { new_tail } from '../utils/tail'; +import Element from './Element'; -function unpack_destructuring(contexts: Array<{ name: string, tail: string }>, node: INode, tail: string) { +type Context = { + key: INode, + name?: string, + tail: string +}; + +function unpack_destructuring(contexts: Array, node: INode, tail: string) { if (!node) return; if (node.type === 'Identifier' || node.type === 'RestIdentifier') { @@ -53,7 +60,7 @@ export default class EachBlock extends AbstractBlock { context: string; key: Expression; scope: TemplateScope; - contexts: Array<{ name: string, tail: string }>; + contexts: Array; has_animation: boolean; has_binding = false; @@ -82,7 +89,7 @@ export default class EachBlock extends AbstractBlock { if (this.index) { // index can only change if this is a keyed each block - const dependencies = this.key ? this.expression.dependencies : []; + const dependencies = this.key ? this.expression.dependencies : new Set([]); this.scope.add(this.index, dependencies, this); } @@ -92,8 +99,8 @@ export default class EachBlock extends AbstractBlock { if (this.has_animation) { if (this.children.length !== 1) { - const child = this.children.find(child => !!child.animation); - component.error(child.animation, { + const child = this.children.find(child => !!(child as Element).animation); + component.error((child as Element).animation, { code: `invalid-animation`, message: `An element that use the animate directive must be the sole child of a keyed each block` }); diff --git a/src/compile/nodes/Element.ts b/src/compile/nodes/Element.ts index 2b76d68e6d..1b2d82188c 100644 --- a/src/compile/nodes/Element.ts +++ b/src/compile/nodes/Element.ts @@ -15,6 +15,7 @@ import fuzzymatch from '../../utils/fuzzymatch'; import list from '../../utils/list'; import Let from './Let'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; const svg = /^(?:altGlyph|altGlyphDef|altGlyphItem|animate|animateColor|animateMotion|animateTransform|circle|clipPath|color-profile|cursor|defs|desc|discard|ellipse|feBlend|feColorMatrix|feComponentTransfer|feComposite|feConvolveMatrix|feDiffuseLighting|feDisplacementMap|feDistantLight|feDropShadow|feFlood|feFuncA|feFuncB|feFuncG|feFuncR|feGaussianBlur|feImage|feMerge|feMergeNode|feMorphology|feOffset|fePointLight|feSpecularLighting|feSpotLight|feTile|feTurbulence|filter|font|font-face|font-face-format|font-face-name|font-face-src|font-face-uri|foreignObject|g|glyph|glyphRef|hatch|hatchpath|hkern|image|line|linearGradient|marker|mask|mesh|meshgradient|meshpatch|meshrow|metadata|missing-glyph|mpath|path|pattern|polygon|polyline|radialGradient|rect|set|solidcolor|stop|svg|switch|symbol|text|textPath|tref|tspan|unknown|use|view|vkern)$/; @@ -101,7 +102,7 @@ export default class Element extends Node { intro?: Transition = null; outro?: Transition = null; animation?: Animation = null; - children: Node[]; + children: INode[]; namespace: string; constructor(component, parent, scope, info: any) { @@ -136,7 +137,7 @@ export default class Element extends Node { // Special case — treat these the same way: // // - const value_attribute = info.attributes.find((attribute: Node) => attribute.name === 'value'); + const value_attribute = info.attributes.find(attribute => attribute.name === 'value'); if (!value_attribute) { info.attributes.push({ @@ -228,7 +229,7 @@ export default class Element extends Node { let is_figure_parent = false; while (parent) { - if (parent.name === 'figure') { + if ((parent as Element).name === 'figure') { is_figure_parent = true; break; } @@ -253,7 +254,7 @@ export default class Element extends Node { return true; }); - const index = children.findIndex(child => child.name === 'figcaption'); + const index = children.findIndex(child => (child as Element).name === 'figcaption'); if (index !== -1 && (index !== 0 && index !== children.length - 1)) { this.component.warn(children[index], { @@ -320,7 +321,9 @@ export default class Element extends Node { } const value = attribute.get_static_value(); + // @ts-ignore if (value && !aria_role_set.has(value)) { + // @ts-ignore const match = fuzzymatch(value, aria_roles); let message = `A11y: Unknown role '${value}'`; if (match) message += ` (did you mean '${match}'?)`; @@ -359,6 +362,7 @@ export default class Element extends Node { // tabindex-no-positive if (name === 'tabindex') { const value = attribute.get_static_value(); + // @ts-ignore todo is tabindex=true correct case? if (!isNaN(value) && +value > 0) { component.warn(attribute, { code: `a11y-positive-tabindex`, diff --git a/src/compile/nodes/ElseBlock.ts b/src/compile/nodes/ElseBlock.ts index 61c1aa5455..5f3aa29529 100644 --- a/src/compile/nodes/ElseBlock.ts +++ b/src/compile/nodes/ElseBlock.ts @@ -1,10 +1,11 @@ import map_children from './shared/map_children'; import AbstractBlock from './shared/AbstractBlock'; +import Component from '../Component'; export default class ElseBlock extends AbstractBlock { type: 'ElseBlock'; - constructor(component, parent, scope, info) { + constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); this.children = map_children(component, this, scope, info.children); diff --git a/src/compile/nodes/EventHandler.ts b/src/compile/nodes/EventHandler.ts index f5e7e0e898..dab60858d5 100644 --- a/src/compile/nodes/EventHandler.ts +++ b/src/compile/nodes/EventHandler.ts @@ -5,6 +5,7 @@ import deindent from '../utils/deindent'; import Block from '../render-dom/Block'; export default class EventHandler extends Node { + type: 'EventHandler'; name: string; modifiers: Set; expression: Expression; @@ -65,4 +66,4 @@ export default class EventHandler extends Node { // this.component.add_reference(this.handler_name); return `ctx.${this.handler_name}`; } -} \ No newline at end of file +} diff --git a/src/compile/nodes/Fragment.ts b/src/compile/nodes/Fragment.ts index ec25d41a1c..6025b036a6 100644 --- a/src/compile/nodes/Fragment.ts +++ b/src/compile/nodes/Fragment.ts @@ -3,10 +3,12 @@ import Component from '../Component'; import map_children from './shared/map_children'; import Block from '../render-dom/Block'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class Fragment extends Node { + type: 'Fragment'; block: Block; - children: Node[]; + children: INode[]; scope: TemplateScope; constructor(component: Component, info: any) { @@ -16,4 +18,4 @@ export default class Fragment extends Node { this.scope = scope; this.children = map_children(component, this, scope, info.children); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/Head.ts b/src/compile/nodes/Head.ts index bc6e9bde40..2c08dcd595 100644 --- a/src/compile/nodes/Head.ts +++ b/src/compile/nodes/Head.ts @@ -1,5 +1,4 @@ import Node from './shared/Node'; -import Block from '../render-dom/Block'; import map_children from './shared/map_children'; export default class Head extends Node { diff --git a/src/compile/nodes/InlineComponent.ts b/src/compile/nodes/InlineComponent.ts index 3359e981ed..8b6cd77282 100644 --- a/src/compile/nodes/InlineComponent.ts +++ b/src/compile/nodes/InlineComponent.ts @@ -7,6 +7,7 @@ import Expression from './shared/Expression'; import Component from '../Component'; import Let from './Let'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class InlineComponent extends Node { type: 'InlineComponent'; @@ -16,7 +17,7 @@ export default class InlineComponent extends Node { bindings: Binding[] = []; handlers: EventHandler[] = []; lets: Let[] = []; - children: Node[]; + children: INode[]; scope: TemplateScope; constructor(component: Component, parent, scope, info) { diff --git a/src/compile/nodes/MustacheTag.ts b/src/compile/nodes/MustacheTag.ts index e668987a9c..ac6688d503 100644 --- a/src/compile/nodes/MustacheTag.ts +++ b/src/compile/nodes/MustacheTag.ts @@ -1,3 +1,5 @@ import Tag from './shared/Tag'; -export default class MustacheTag extends Tag {} \ No newline at end of file +export default class MustacheTag extends Tag { + type: 'MustacheTag'; +} diff --git a/src/compile/nodes/PendingBlock.ts b/src/compile/nodes/PendingBlock.ts index 0fd71c0221..5ff7352558 100644 --- a/src/compile/nodes/PendingBlock.ts +++ b/src/compile/nodes/PendingBlock.ts @@ -2,7 +2,7 @@ import map_children from './shared/map_children'; import AbstractBlock from './shared/AbstractBlock'; export default class PendingBlock extends AbstractBlock { - + type: 'PendingBlock'; constructor(component, parent, scope, info) { super(component, parent, scope, info); this.children = map_children(component, parent, scope, info.children); diff --git a/src/compile/nodes/RawMustacheTag.ts b/src/compile/nodes/RawMustacheTag.ts index ada3123410..fc63885942 100644 --- a/src/compile/nodes/RawMustacheTag.ts +++ b/src/compile/nodes/RawMustacheTag.ts @@ -1,3 +1,5 @@ import Tag from './shared/Tag'; -export default class RawMustacheTag extends Tag {} \ No newline at end of file +export default class RawMustacheTag extends Tag { + type: 'RawMustacheTag' +} diff --git a/src/compile/nodes/Slot.ts b/src/compile/nodes/Slot.ts index dbb502b41a..a03fe8c026 100644 --- a/src/compile/nodes/Slot.ts +++ b/src/compile/nodes/Slot.ts @@ -1,17 +1,17 @@ -import Node from './shared/Node'; import Element from './Element'; import Attribute from './Attribute'; import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class Slot extends Element { type: 'Element'; name: string; - children: Node[]; + children: INode[]; slot_name: string; values: Map = new Map(); - constructor(component: Component, parent: Node, scope: TemplateScope, info: any) { + constructor(component: Component, parent: INode, scope: TemplateScope, info: any) { super(component, parent, scope, info); info.attributes.forEach(attr => { @@ -68,4 +68,4 @@ export default class Slot extends Element { component.slots.set(this.slot_name, this); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/Text.ts b/src/compile/nodes/Text.ts index 1c31c9d83d..7500f5ff30 100644 --- a/src/compile/nodes/Text.ts +++ b/src/compile/nodes/Text.ts @@ -1,13 +1,14 @@ import Node from './shared/Node'; import Component from '../Component'; import TemplateScope from './shared/TemplateScope'; +import { INode } from './interfaces'; export default class Text extends Node { type: 'Text'; data: string; use_space = false; - constructor(component: Component, parent: Node, scope: TemplateScope, info: any) { + constructor(component: Component, parent: INode, scope: TemplateScope, info: any) { super(component, parent, scope, info); this.data = info.data; @@ -23,4 +24,4 @@ export default class Text extends Node { this.use_space = true; } } -} \ No newline at end of file +} diff --git a/src/compile/nodes/ThenBlock.ts b/src/compile/nodes/ThenBlock.ts index 7e4ed0e5da..7f9bbde0f0 100644 --- a/src/compile/nodes/ThenBlock.ts +++ b/src/compile/nodes/ThenBlock.ts @@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope'; import AbstractBlock from './shared/AbstractBlock'; export default class ThenBlock extends AbstractBlock { + type: 'ThenBlock'; scope: TemplateScope; constructor(component, parent, scope, info) { diff --git a/src/compile/nodes/Title.ts b/src/compile/nodes/Title.ts index fd58d3043d..6ac0848053 100644 --- a/src/compile/nodes/Title.ts +++ b/src/compile/nodes/Title.ts @@ -1,12 +1,13 @@ import Node from './shared/Node'; -import map_children from './shared/map_children'; +import map_children, { Children } from './shared/map_children'; +import Component from '../Component'; export default class Title extends Node { type: 'Title'; - children: any[]; // TODO + children: Children; should_cache: boolean; - constructor(component, parent, scope, info) { + constructor(component: Component, parent, scope, info) { super(component, parent, scope, info); this.children = map_children(component, parent, scope, info.children); @@ -33,4 +34,4 @@ export default class Title extends Node { ) : true; } -} \ No newline at end of file +} diff --git a/src/compile/nodes/interfaces.ts b/src/compile/nodes/interfaces.ts new file mode 100644 index 0000000000..434b09e5aa --- /dev/null +++ b/src/compile/nodes/interfaces.ts @@ -0,0 +1,64 @@ +import Tag from './shared/Tag'; + +import Action from './Action'; +import Animation from './Animation'; +import Attribute from './Attribute'; +import AwaitBlock from './AwaitBlock'; +import Binding from './Binding'; +import Body from './Body'; +import CatchBlock from './CatchBlock'; +import Class from './Class'; +import Comment from './Comment'; +import DebugTag from './DebugTag'; +import EachBlock from './EachBlock'; +import Element from './Element'; +import ElseBlock from './ElseBlock'; +import EventHandler from './EventHandler'; +import Fragment from './Fragment'; +import Head from './Head'; +import IfBlock from './IfBlock'; +import InlineComponent from './InlineComponent'; +import Let from './Let'; +import MustacheTag from './MustacheTag'; +import Options from './Options'; +import PendingBlock from './PendingBlock'; +import RawMustacheTag from './RawMustacheTag'; +import Slot from './Slot'; +import Text from './Text'; +import ThenBlock from './ThenBlock'; +import Title from './Title'; +import Transition from './Transition'; +import Window from './Window'; + +// note: to write less types each of types in union below should have type defined as literal +// https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions +export type INode = Action + | Animation + | Attribute + | AwaitBlock + | Binding + | Body + | CatchBlock + | Class + | Comment + | DebugTag + | EachBlock + | Element + | ElseBlock + | EventHandler + | Fragment + | Head + | IfBlock + | InlineComponent + | Let + | MustacheTag + | Options + | PendingBlock + | RawMustacheTag + | Slot + | Tag + | Text + | ThenBlock + | Title + | Transition + | Window; diff --git a/src/compile/nodes/shared/AbstractBlock.ts b/src/compile/nodes/shared/AbstractBlock.ts index 1dfebd51f0..e1104e4928 100644 --- a/src/compile/nodes/shared/AbstractBlock.ts +++ b/src/compile/nodes/shared/AbstractBlock.ts @@ -1,10 +1,11 @@ import Block from '../../render-dom/Block'; import Component from './../../Component'; import Node from './Node'; +import { INode } from '../interfaces'; export default class AbstractBlock extends Node { block: Block; - children: Node[]; + children: INode[]; constructor(component: Component, parent, scope, info: any) { super(component, parent, scope, info); diff --git a/src/compile/nodes/shared/Expression.ts b/src/compile/nodes/shared/Expression.ts index fc188e9673..e7c63dfec2 100644 --- a/src/compile/nodes/shared/Expression.ts +++ b/src/compile/nodes/shared/Expression.ts @@ -12,6 +12,7 @@ import TemplateScope from './TemplateScope'; import get_object from '../../utils/get_object'; import { nodes_match } from '../../../utils/nodes_match'; import Block from '../../render-dom/Block'; +import { INode } from '../interfaces'; const binary_operators: Record = { '**': 15, @@ -61,10 +62,12 @@ const precedence: Record number> = { SequenceExpression: () => 0 }; +type Owner = Wrapper | INode; + export default class Expression { - type = 'Expression'; + type: 'Expression' = 'Expression'; component: Component; - owner: Wrapper; + owner: Owner; node: any; snippet: string; references: Set; @@ -81,7 +84,8 @@ export default class Expression { rendered: string; - constructor(component: Component, owner: Wrapper, template_scope: TemplateScope, info) { + // todo: owner type + constructor(component: Component, owner: Owner, template_scope: TemplateScope, info) { // TODO revert to direct property access in prod? Object.defineProperties(this, { component: { @@ -92,6 +96,7 @@ export default class Expression { this.node = info; this.template_scope = template_scope; this.owner = owner; + // @ts-ignore this.is_synthetic = owner.is_synthetic; const { dependencies, contextual_dependencies } = this; @@ -218,7 +223,7 @@ export default class Expression { } // TODO move this into a render-dom wrapper? - render(block: Block) { + render(block?: Block) { if (this.rendered) return this.rendered; const { @@ -510,4 +515,4 @@ function is_contextual(component: Component, scope: TemplateScope, name: string) // assume contextual return true; -} \ No newline at end of file +} diff --git a/src/compile/nodes/shared/Node.ts b/src/compile/nodes/shared/Node.ts index b6eaf9965d..b647e3a158 100644 --- a/src/compile/nodes/shared/Node.ts +++ b/src/compile/nodes/shared/Node.ts @@ -1,15 +1,17 @@ import Attribute from './../Attribute'; import Component from './../../Component'; +import { INode } from '../interfaces'; +import Text from '../Text'; export default class Node { readonly start: number; readonly end: number; readonly component: Component; - readonly parent: Node; + readonly parent: INode; readonly type: string; - prev?: Node; - next?: Node; + prev?: INode; + next?: INode; can_use_innerhtml: boolean; var: string; @@ -55,7 +57,7 @@ export default class Node { if (attribute.chunks.length === 0) return ''; if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') { - return attribute.chunks[0].data; + return (attribute.chunks[0] as Text).data; } return null; diff --git a/src/compile/nodes/shared/Tag.ts b/src/compile/nodes/shared/Tag.ts index 94971bef11..bc826458d9 100644 --- a/src/compile/nodes/shared/Tag.ts +++ b/src/compile/nodes/shared/Tag.ts @@ -2,6 +2,7 @@ import Node from './Node'; import Expression from './Expression'; export default class Tag extends Node { + type: 'MustacheTag' | 'RawMustacheTag'; expression: Expression; should_cache: boolean; @@ -14,4 +15,4 @@ export default class Tag extends Node { (this.expression.dependencies.size && scope.names.has(info.expression.name)) ); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/shared/TemplateScope.ts b/src/compile/nodes/shared/TemplateScope.ts index abd366642e..5f30d0c883 100644 --- a/src/compile/nodes/shared/TemplateScope.ts +++ b/src/compile/nodes/shared/TemplateScope.ts @@ -2,6 +2,7 @@ import EachBlock from '../EachBlock'; import ThenBlock from '../ThenBlock'; import CatchBlock from '../CatchBlock'; import InlineComponent from '../InlineComponent'; +import Element from '../Element'; type NodeWithScope = EachBlock | ThenBlock | CatchBlock | InlineComponent | Element; @@ -41,4 +42,4 @@ export default class TemplateScope { const owner = this.get_owner(name); return owner && (owner.type === 'Element' || owner.type === 'InlineComponent'); } -} \ No newline at end of file +} diff --git a/src/compile/nodes/shared/map_children.ts b/src/compile/nodes/shared/map_children.ts index b903853016..71d764a889 100644 --- a/src/compile/nodes/shared/map_children.ts +++ b/src/compile/nodes/shared/map_children.ts @@ -14,9 +14,11 @@ import Slot from '../Slot'; import Text from '../Text'; import Title from '../Title'; import Window from '../Window'; -import Node from './Node'; +import { Node } from '../../../interfaces'; -function get_constructor(type): typeof Node { +export type Children = ReturnType; + +function get_constructor(type) { switch (type) { case 'AwaitBlock': return AwaitBlock; case 'Body': return Body; @@ -38,7 +40,7 @@ function get_constructor(type): typeof Node { } } -export default function map_children(component, parent, scope, children: any[]) { +export default function map_children(component, parent, scope, children: Node[]) { let last = null; return children.map(child => { const constructor = get_constructor(child.type); diff --git a/src/compile/render-dom/Block.ts b/src/compile/render-dom/Block.ts index e40b3ceb55..531826edcb 100644 --- a/src/compile/render-dom/Block.ts +++ b/src/compile/render-dom/Block.ts @@ -9,7 +9,7 @@ export interface BlockOptions { renderer?: Renderer; comment?: string; key?: string; - bindings?: Map { object: string, property: string, snippet: string }>; + bindings?: Map; dependencies?: Set; } diff --git a/src/compile/render-dom/Renderer.ts b/src/compile/render-dom/Renderer.ts index 1d766c6345..ea07c1544f 100644 --- a/src/compile/render-dom/Renderer.ts +++ b/src/compile/render-dom/Renderer.ts @@ -3,7 +3,6 @@ import { CompileOptions } from '../../interfaces'; import Component from '../Component'; import FragmentWrapper from './wrappers/Fragment'; import CodeBuilder from '../utils/CodeBuilder'; -import SlotWrapper from './wrappers/Slot'; export default class Renderer { component: Component; // TODO Maybe Renderer shouldn't know about Component? @@ -18,6 +17,7 @@ export default class Renderer { fragment: FragmentWrapper; file_var: string; + locate: (c: number) => { line: number; column: number; }; constructor(component: Component, options: CompileOptions) { this.component = component; @@ -58,4 +58,4 @@ export default class Renderer { this.fragment.render(this.block, null, 'nodes'); } -} \ No newline at end of file +} diff --git a/src/compile/render-dom/wrappers/EachBlock.ts b/src/compile/render-dom/wrappers/EachBlock.ts index fe5d5746e5..9208c838ad 100644 --- a/src/compile/render-dom/wrappers/EachBlock.ts +++ b/src/compile/render-dom/wrappers/EachBlock.ts @@ -8,7 +8,7 @@ import deindent from '../../utils/deindent'; import ElseBlock from '../../nodes/ElseBlock'; import { attach_head } from '../../utils/tail'; -class ElseBlockWrapper extends Wrapper { +export class ElseBlockWrapper extends Wrapper { node: ElseBlock; block: Block; fragment: FragmentWrapper; @@ -83,6 +83,7 @@ export default class EachBlockWrapper extends Wrapper { this.block = block.child({ comment: create_debugging_comment(this.node, this.renderer.component), name: renderer.component.get_unique_name('create_each_block'), + // @ts-ignore todo: probably error key: node.key as string, bindings: new Map(block.bindings) @@ -310,7 +311,9 @@ export default class EachBlockWrapper extends Wrapper { } block.builders.init.add_block(deindent` - const ${get_key} = ctx => ${this.node.key.render()}; + const ${get_key} = ctx => ${ + // @ts-ignore todo: probably error + this.node.key.render()}; for (var #i = 0; #i < ${this.vars.each_block_value}.${length}; #i += 1) { let child_ctx = ${this.vars.get_each_context}(ctx, ${this.vars.each_block_value}, #i); diff --git a/src/compile/render-dom/wrappers/Element/Attribute.ts b/src/compile/render-dom/wrappers/Element/Attribute.ts index 5007724f34..876496e2f6 100644 --- a/src/compile/render-dom/wrappers/Element/Attribute.ts +++ b/src/compile/render-dom/wrappers/Element/Attribute.ts @@ -4,6 +4,7 @@ import fix_attribute_casing from './fix_attribute_casing'; import ElementWrapper from './index'; import { stringify } from '../../../utils/stringify'; import deindent from '../../../utils/deindent'; +import Expression from '../../../nodes/shared/Expression'; export default class AttributeWrapper { node: Attribute; @@ -21,7 +22,9 @@ export default class AttributeWrapper { // special case —