fix compile/nodes typings

pull/2838/head
Bogdan Savluk 5 years ago
parent 6fdaa803c7
commit b7ec99e8c7

@ -67,6 +67,7 @@ export default class Attribute extends Node {
this.should_cache = this.is_dynamic this.should_cache = this.is_dynamic
? this.chunks.length === 1 ? this.chunks.length === 1
// @ts-ignore todo: probably error
? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name) ? this.chunks[0].node.type !== 'Identifier' || scope.names.has(this.chunks[0].node.name)
: true : true
: false; : false;
@ -91,8 +92,10 @@ export default class Attribute extends Node {
if (this.chunks.length === 0) return `""`; if (this.chunks.length === 0) return `""`;
if (this.chunks.length === 1) { if (this.chunks.length === 1) {
return this.chunks[0].type === 'Text' 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); : this.chunks[0].render(block);
} }
@ -102,6 +105,7 @@ export default class Attribute extends Node {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return stringify(chunk.data); return stringify(chunk.data);
} else { } else {
// @ts-ignore todo: probably error
return chunk.get_precedence() <= 13 ? `(${chunk.render()})` : chunk.render(); return chunk.get_precedence() <= 13 ? `(${chunk.render()})` : chunk.render();
} }
}) })
@ -114,7 +118,8 @@ export default class Attribute extends Node {
return this.is_true return this.is_true
? true ? true
: this.chunks[0] : this.chunks[0]
? this.chunks[0].data // method should be called only when `is_static = true`
? (this.chunks[0] as Text).data
: ''; : '';
} }
} }

@ -5,6 +5,7 @@ import CatchBlock from './CatchBlock';
import Expression from './shared/Expression'; import Expression from './shared/Expression';
export default class AwaitBlock extends Node { export default class AwaitBlock extends Node {
type: 'AwaitBlock';
expression: Expression; expression: Expression;
value: string; value: string;
error: string; error: string;

@ -5,6 +5,7 @@ import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
export default class Binding extends Node { export default class Binding extends Node {
type: 'Binding';
name: string; name: string;
expression: Expression; expression: Expression;
is_contextual: boolean; is_contextual: boolean;

@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
export default class CatchBlock extends AbstractBlock { export default class CatchBlock extends AbstractBlock {
type: 'CatchBlock';
scope: TemplateScope; scope: TemplateScope;
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {

@ -2,6 +2,7 @@ import Node from './shared/Node';
import Expression from './shared/Expression'; import Expression from './shared/Expression';
export default class DebugTag extends Node { export default class DebugTag extends Node {
type: 'DebugTag';
expressions: Expression[]; expressions: Expression[];
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {
@ -11,4 +12,4 @@ export default class DebugTag extends Node {
return new Expression(component, parent, scope, node); return new Expression(component, parent, scope, node);
}); });
} }
} }

@ -6,8 +6,15 @@ import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
import { Node as INode } from '../../interfaces'; import { Node as INode } from '../../interfaces';
import { new_tail } from '../utils/tail'; 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<Context>, node: INode, tail: string) {
if (!node) return; if (!node) return;
if (node.type === 'Identifier' || node.type === 'RestIdentifier') { if (node.type === 'Identifier' || node.type === 'RestIdentifier') {
@ -53,7 +60,7 @@ export default class EachBlock extends AbstractBlock {
context: string; context: string;
key: Expression; key: Expression;
scope: TemplateScope; scope: TemplateScope;
contexts: Array<{ name: string, tail: string }>; contexts: Array<Context>;
has_animation: boolean; has_animation: boolean;
has_binding = false; has_binding = false;
@ -82,7 +89,7 @@ export default class EachBlock extends AbstractBlock {
if (this.index) { if (this.index) {
// index can only change if this is a keyed each block // 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); this.scope.add(this.index, dependencies, this);
} }
@ -92,8 +99,8 @@ export default class EachBlock extends AbstractBlock {
if (this.has_animation) { if (this.has_animation) {
if (this.children.length !== 1) { if (this.children.length !== 1) {
const child = this.children.find(child => !!child.animation); const child = this.children.find(child => !!(child as Element).animation);
component.error(child.animation, { component.error((child as Element).animation, {
code: `invalid-animation`, code: `invalid-animation`,
message: `An element that use the animate directive must be the sole child of a keyed each block` message: `An element that use the animate directive must be the sole child of a keyed each block`
}); });

@ -15,6 +15,7 @@ import fuzzymatch from '../../utils/fuzzymatch';
import list from '../../utils/list'; import list from '../../utils/list';
import Let from './Let'; import Let from './Let';
import TemplateScope from './shared/TemplateScope'; 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)$/; 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; intro?: Transition = null;
outro?: Transition = null; outro?: Transition = null;
animation?: Animation = null; animation?: Animation = null;
children: Node[]; children: INode[];
namespace: string; namespace: string;
constructor(component, parent, scope, info: any) { constructor(component, parent, scope, info: any) {
@ -136,7 +137,7 @@ export default class Element extends Node {
// Special case — treat these the same way: // Special case — treat these the same way:
// <option>{foo}</option> // <option>{foo}</option>
// <option value={foo}>{foo}</option> // <option value={foo}>{foo}</option>
const value_attribute = info.attributes.find((attribute: Node) => attribute.name === 'value'); const value_attribute = info.attributes.find(attribute => attribute.name === 'value');
if (!value_attribute) { if (!value_attribute) {
info.attributes.push({ info.attributes.push({
@ -228,7 +229,7 @@ export default class Element extends Node {
let is_figure_parent = false; let is_figure_parent = false;
while (parent) { while (parent) {
if (parent.name === 'figure') { if ((parent as Element).name === 'figure') {
is_figure_parent = true; is_figure_parent = true;
break; break;
} }
@ -249,11 +250,11 @@ export default class Element extends Node {
if (this.name === 'figure') { if (this.name === 'figure') {
const children = this.children.filter(node => { const children = this.children.filter(node => {
if (node.type === 'Comment') return false; if (node.type === 'Comment') return false;
if (node.type === 'Text') return /\S/.test(node.data); if (node.type === 'Text') return /\S/.test((node as Text).data );
return true; 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)) { if (index !== -1 && (index !== 0 && index !== children.length - 1)) {
this.component.warn(children[index], { this.component.warn(children[index], {
@ -320,7 +321,9 @@ export default class Element extends Node {
} }
const value = attribute.get_static_value(); const value = attribute.get_static_value();
// @ts-ignore
if (value && !aria_role_set.has(value)) { if (value && !aria_role_set.has(value)) {
// @ts-ignore
const match = fuzzymatch(value, aria_roles); const match = fuzzymatch(value, aria_roles);
let message = `A11y: Unknown role '${value}'`; let message = `A11y: Unknown role '${value}'`;
if (match) message += ` (did you mean '${match}'?)`; if (match) message += ` (did you mean '${match}'?)`;
@ -359,6 +362,7 @@ export default class Element extends Node {
// tabindex-no-positive // tabindex-no-positive
if (name === 'tabindex') { if (name === 'tabindex') {
const value = attribute.get_static_value(); const value = attribute.get_static_value();
// @ts-ignore todo is tabindex=true correct case?
if (!isNaN(value) && +value > 0) { if (!isNaN(value) && +value > 0) {
component.warn(attribute, { component.warn(attribute, {
code: `a11y-positive-tabindex`, code: `a11y-positive-tabindex`,
@ -387,7 +391,7 @@ export default class Element extends Node {
let ancestor = this.parent; let ancestor = this.parent;
do { do {
if (ancestor.type === 'InlineComponent') break; if (ancestor.type === 'InlineComponent') break;
if (ancestor.type === 'Element' && /-/.test(ancestor.name)) break; if (ancestor.type === 'Element' && /-/.test((ancestor as Element).name)) break;
if (ancestor.type === 'IfBlock' || ancestor.type === 'EachBlock') { if (ancestor.type === 'IfBlock' || ancestor.type === 'EachBlock') {
const type = ancestor.type === 'IfBlock' ? 'if' : 'each'; const type = ancestor.type === 'IfBlock' ? 'if' : 'each';

@ -1,10 +1,11 @@
import map_children from './shared/map_children'; import map_children from './shared/map_children';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
import Component from '../Component';
export default class ElseBlock extends AbstractBlock { export default class ElseBlock extends AbstractBlock {
type: 'ElseBlock'; type: 'ElseBlock';
constructor(component, parent, scope, info) { constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
this.children = map_children(component, this, scope, info.children); this.children = map_children(component, this, scope, info.children);

@ -5,6 +5,7 @@ import deindent from '../utils/deindent';
import Block from '../render-dom/Block'; import Block from '../render-dom/Block';
export default class EventHandler extends Node { export default class EventHandler extends Node {
type: 'EventHandler';
name: string; name: string;
modifiers: Set<string>; modifiers: Set<string>;
expression: Expression; expression: Expression;
@ -65,4 +66,4 @@ export default class EventHandler extends Node {
// this.component.add_reference(this.handler_name); // this.component.add_reference(this.handler_name);
return `ctx.${this.handler_name}`; return `ctx.${this.handler_name}`;
} }
} }

@ -3,10 +3,12 @@ import Component from '../Component';
import map_children from './shared/map_children'; import map_children from './shared/map_children';
import Block from '../render-dom/Block'; import Block from '../render-dom/Block';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
export default class Fragment extends Node { export default class Fragment extends Node {
type: 'Fragment';
block: Block; block: Block;
children: Node[]; children: INode[];
scope: TemplateScope; scope: TemplateScope;
constructor(component: Component, info: any) { constructor(component: Component, info: any) {
@ -16,4 +18,4 @@ export default class Fragment extends Node {
this.scope = scope; this.scope = scope;
this.children = map_children(component, this, scope, info.children); this.children = map_children(component, this, scope, info.children);
} }
} }

@ -1,5 +1,4 @@
import Node from './shared/Node'; import Node from './shared/Node';
import Block from '../render-dom/Block';
import map_children from './shared/map_children'; import map_children from './shared/map_children';
export default class Head extends Node { export default class Head extends Node {

@ -7,6 +7,7 @@ import Expression from './shared/Expression';
import Component from '../Component'; import Component from '../Component';
import Let from './Let'; import Let from './Let';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
export default class InlineComponent extends Node { export default class InlineComponent extends Node {
type: 'InlineComponent'; type: 'InlineComponent';
@ -16,7 +17,7 @@ export default class InlineComponent extends Node {
bindings: Binding[] = []; bindings: Binding[] = [];
handlers: EventHandler[] = []; handlers: EventHandler[] = [];
lets: Let[] = []; lets: Let[] = [];
children: Node[]; children: INode[];
scope: TemplateScope; scope: TemplateScope;
constructor(component: Component, parent, scope, info) { constructor(component: Component, parent, scope, info) {

@ -1,3 +1,5 @@
import Tag from './shared/Tag'; import Tag from './shared/Tag';
export default class MustacheTag extends Tag {} export default class MustacheTag extends Tag {
type: 'MustacheTag';
}

@ -2,7 +2,7 @@ import map_children from './shared/map_children';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
export default class PendingBlock extends AbstractBlock { export default class PendingBlock extends AbstractBlock {
type: 'PendingBlock';
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
this.children = map_children(component, parent, scope, info.children); this.children = map_children(component, parent, scope, info.children);

@ -1,3 +1,5 @@
import Tag from './shared/Tag'; import Tag from './shared/Tag';
export default class RawMustacheTag extends Tag {} export default class RawMustacheTag extends Tag {
type: 'RawMustacheTag'
}

@ -1,17 +1,17 @@
import Node from './shared/Node';
import Element from './Element'; import Element from './Element';
import Attribute from './Attribute'; import Attribute from './Attribute';
import Component from '../Component'; import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
export default class Slot extends Element { export default class Slot extends Element {
type: 'Element'; type: 'Element';
name: string; name: string;
children: Node[]; children: INode[];
slot_name: string; slot_name: string;
values: Map<string, Attribute> = new Map(); values: Map<string, Attribute> = 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); super(component, parent, scope, info);
info.attributes.forEach(attr => { info.attributes.forEach(attr => {
@ -68,4 +68,4 @@ export default class Slot extends Element {
component.slots.set(this.slot_name, this); component.slots.set(this.slot_name, this);
} }
} }

@ -1,20 +1,22 @@
import Node from './shared/Node'; import Node from './shared/Node';
import Component from '../Component'; import Component from '../Component';
import TemplateScope from './shared/TemplateScope'; import TemplateScope from './shared/TemplateScope';
import { INode } from './interfaces';
import Element from './Element';
export default class Text extends Node { export default class Text extends Node {
type: 'Text'; type: 'Text';
data: string; data: string;
use_space = false; 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); super(component, parent, scope, info);
this.data = info.data; this.data = info.data;
if (!component.component_options.preserveWhitespace && !/\S/.test(info.data)) { if (!component.component_options.preserveWhitespace && !/\S/.test(info.data)) {
let node = parent; let node = parent;
while (node) { while (node) {
if (node.type === 'Element' && node.name === 'pre') { if (node.type === 'Element' && (node as Element).name === 'pre') {
return; return;
} }
node = node.parent; node = node.parent;
@ -23,4 +25,4 @@ export default class Text extends Node {
this.use_space = true; this.use_space = true;
} }
} }
} }

@ -3,6 +3,7 @@ import TemplateScope from './shared/TemplateScope';
import AbstractBlock from './shared/AbstractBlock'; import AbstractBlock from './shared/AbstractBlock';
export default class ThenBlock extends AbstractBlock { export default class ThenBlock extends AbstractBlock {
type: 'ThenBlock';
scope: TemplateScope; scope: TemplateScope;
constructor(component, parent, scope, info) { constructor(component, parent, scope, info) {

@ -1,12 +1,14 @@
import Node from './shared/Node'; 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 { export default class Title extends Node {
type: 'Title'; type: 'Title';
children: any[]; // TODO
should_cache: boolean; should_cache: boolean;
children: Children;
constructor(component, parent, scope, info) { constructor(component: Component, parent, scope, info) {
super(component, parent, scope, info); super(component, parent, scope, info);
this.children = map_children(component, parent, scope, info.children); this.children = map_children(component, parent, scope, info.children);
@ -33,4 +35,4 @@ export default class Title extends Node {
) )
: true; : true;
} }
} }

@ -0,0 +1,62 @@
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';
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;

@ -1,10 +1,11 @@
import Block from '../../render-dom/Block'; import Block from '../../render-dom/Block';
import Component from './../../Component'; import Component from './../../Component';
import Node from './Node'; import Node from './Node';
import { INode } from '../interfaces';
export default class AbstractBlock extends Node { export default class AbstractBlock extends Node {
block: Block; block: Block;
children: Node[]; children: INode[];
constructor(component: Component, parent, scope, info: any) { constructor(component: Component, parent, scope, info: any) {
super(component, parent, scope, info); super(component, parent, scope, info);

@ -12,6 +12,7 @@ import TemplateScope from './TemplateScope';
import get_object from '../../utils/get_object'; import get_object from '../../utils/get_object';
import { nodes_match } from '../../../utils/nodes_match'; import { nodes_match } from '../../../utils/nodes_match';
import Block from '../../render-dom/Block'; import Block from '../../render-dom/Block';
import { INode } from '../interfaces';
const binary_operators: Record<string, number> = { const binary_operators: Record<string, number> = {
'**': 15, '**': 15,
@ -61,10 +62,12 @@ const precedence: Record<string, (node?: Node) => number> = {
SequenceExpression: () => 0 SequenceExpression: () => 0
}; };
type Owner = Wrapper | INode;
export default class Expression { export default class Expression {
type = 'Expression'; type: 'Expression' = 'Expression';
component: Component; component: Component;
owner: Wrapper; owner: Owner;
node: any; node: any;
snippet: string; snippet: string;
references: Set<string>; references: Set<string>;
@ -81,7 +84,8 @@ export default class Expression {
rendered: string; 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? // TODO revert to direct property access in prod?
Object.defineProperties(this, { Object.defineProperties(this, {
component: { component: {
@ -92,6 +96,7 @@ export default class Expression {
this.node = info; this.node = info;
this.template_scope = template_scope; this.template_scope = template_scope;
this.owner = owner; this.owner = owner;
// @ts-ignore
this.is_synthetic = owner.is_synthetic; this.is_synthetic = owner.is_synthetic;
const { dependencies, contextual_dependencies } = this; const { dependencies, contextual_dependencies } = this;
@ -510,4 +515,4 @@ function is_contextual(component: Component, scope: TemplateScope, name: string)
// assume contextual // assume contextual
return true; return true;
} }

@ -1,21 +1,23 @@
import Attribute from './../Attribute'; import Attribute from './../Attribute';
import Component from './../../Component'; import Component from './../../Component';
import { INode } from '../interfaces';
import Text from '../Text';
export default class Node { export default class Node {
readonly start: number; readonly start: number;
readonly end: number; readonly end: number;
readonly component: Component; readonly component: Component;
readonly parent: Node; readonly parent: INode;
readonly type: string; readonly type: string;
prev?: Node; prev?: INode;
next?: Node; next?: INode;
can_use_innerhtml: boolean; can_use_innerhtml: boolean;
var: string; var: string;
attributes: Attribute[]; attributes: Attribute[];
constructor(component: Component, parent, scope, info: any) { constructor(component: Component, parent: any, scope: any, info: { start: number; end: number; type: string; }) {
this.start = info.start; this.start = info.start;
this.end = info.end; this.end = info.end;
this.type = info.type; this.type = info.type;
@ -55,7 +57,7 @@ export default class Node {
if (attribute.chunks.length === 0) return ''; if (attribute.chunks.length === 0) return '';
if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') { if (attribute.chunks.length === 1 && attribute.chunks[0].type === 'Text') {
return attribute.chunks[0].data; return (attribute.chunks[0] as Text).data;
} }
return null; return null;

@ -2,6 +2,7 @@ import Node from './Node';
import Expression from './Expression'; import Expression from './Expression';
export default class Tag extends Node { export default class Tag extends Node {
type: 'MustacheTag' | 'RawMustacheTag';
expression: Expression; expression: Expression;
should_cache: boolean; should_cache: boolean;
@ -14,4 +15,4 @@ export default class Tag extends Node {
(this.expression.dependencies.size && scope.names.has(info.expression.name)) (this.expression.dependencies.size && scope.names.has(info.expression.name))
); );
} }
} }

@ -2,6 +2,7 @@ import EachBlock from '../EachBlock';
import ThenBlock from '../ThenBlock'; import ThenBlock from '../ThenBlock';
import CatchBlock from '../CatchBlock'; import CatchBlock from '../CatchBlock';
import InlineComponent from '../InlineComponent'; import InlineComponent from '../InlineComponent';
import Element from '../Element';
type NodeWithScope = EachBlock | ThenBlock | CatchBlock | InlineComponent | Element; type NodeWithScope = EachBlock | ThenBlock | CatchBlock | InlineComponent | Element;
@ -41,4 +42,4 @@ export default class TemplateScope {
const owner = this.get_owner(name); const owner = this.get_owner(name);
return owner && (owner.type === 'Element' || owner.type === 'InlineComponent'); return owner && (owner.type === 'Element' || owner.type === 'InlineComponent');
} }
} }

@ -14,9 +14,11 @@ import Slot from '../Slot';
import Text from '../Text'; import Text from '../Text';
import Title from '../Title'; import Title from '../Title';
import Window from '../Window'; import Window from '../Window';
import Node from './Node'; import { Node } from '../../../interfaces';
function get_constructor(type): typeof Node { export type Children = ReturnType<typeof map_children>;
function get_constructor(type) {
switch (type) { switch (type) {
case 'AwaitBlock': return AwaitBlock; case 'AwaitBlock': return AwaitBlock;
case 'Body': return Body; 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; let last = null;
return children.map(child => { return children.map(child => {
const constructor = get_constructor(child.type); const constructor = get_constructor(child.type);

@ -1,5 +1,6 @@
export default function add_to_set(a: Set<any>, b: Set<any>) { export default function add_to_set<T>(a: Set<T>, b: Set<T> | Array<T>) {
// @ts-ignore
b.forEach(item => { b.forEach(item => {
a.add(item); a.add(item);
}); });
} }

@ -9,7 +9,7 @@ export function create_scopes(expression: Node) {
let scope = new Scope(null, false); let scope = new Scope(null, false);
walk(expression, { walk(expression, {
enter(node: Node, parent: Node) { enter(node, parent) {
if (node.type === 'ImportDeclaration') { if (node.type === 'ImportDeclaration') {
node.specifiers.forEach(specifier => { node.specifiers.forEach(specifier => {
scope.declarations.set(specifier.local.name, specifier); scope.declarations.set(specifier.local.name, specifier);
@ -25,7 +25,7 @@ export function create_scopes(expression: Node) {
if (node.id) scope.declarations.set(node.id.name, node); if (node.id) scope.declarations.set(node.id.name, node);
} }
node.params.forEach((param: Node) => { node.params.forEach((param) => {
extract_names(param).forEach(name => { extract_names(param).forEach(name => {
scope.declarations.set(name, node); scope.declarations.set(name, node);
}); });

@ -1,11 +1,10 @@
import Attribute from '../nodes/Attribute'; import Attribute from '../nodes/Attribute';
import Node from '../nodes/shared/Node';
import { escape_template, escape } from './stringify'; import { escape_template, escape } from './stringify';
import { snip } from './snip'; import { snip } from './snip';
export function stringify_attribute(attribute: Attribute, is_ssr: boolean) { export function stringify_attribute(attribute: Attribute, is_ssr: boolean) {
return attribute.chunks return attribute.chunks
.map((chunk: Node) => { .map((chunk) => {
if (chunk.type === 'Text') { if (chunk.type === 'Text') {
return escape_template(escape(chunk.data).replace(/"/g, '&quot;')); return escape_template(escape(chunk.data).replace(/"/g, '&quot;'));
} }
@ -15,4 +14,4 @@ export function stringify_attribute(attribute: Attribute, is_ssr: boolean) {
: '${' + snip(chunk) + '}'; : '${' + snip(chunk) + '}';
}) })
.join(''); .join('');
} }

Loading…
Cancel
Save