compile/render-dom and other remaining typings

pull/2838/head
Bogdan Savluk 6 years ago
parent 231603df7b
commit 24abeb1d28

8
package-lock.json generated

@ -1,6 +1,6 @@
{
"name": "svelte",
"version": "3.4.0",
"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": {

@ -84,7 +84,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": [

@ -776,7 +776,7 @@ export default class Component {
});
}
invalidate(name, value) {
invalidate(name, value?) {
const variable = this.var_lookup.get(name);
if (variable && (variable.subscribable && variable.reassigned)) {

@ -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(/[\/\\]/);

@ -223,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 {

@ -9,7 +9,7 @@ export interface BlockOptions {
renderer?: Renderer;
comment?: string;
key?: string;
bindings?: Map<string, () => { object: string, property: string, snippet: string }>;
bindings?: Map<string, { object: string, property: string, snippet: string }>;
dependencies?: Set<string>;
}

@ -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;

@ -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);

@ -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 — <option value={foo}> — see below
if (this.parent.node.name === 'option' && node.name === 'value') {
let select: ElementWrapper = this.parent;
while (select && (select.node.type !== 'Element' || select.node.name !== 'select')) select = select.parent;
while (select && (select.node.type !== 'Element' || select.node.name !== 'select'))
// @ts-ignore todo: doublecheck this, but looks to be correct
select = select.parent;
if (select && select.select_binding_dependencies) {
select.select_binding_dependencies.forEach(prop => {
@ -47,7 +50,7 @@ export default class AttributeWrapper {
(element.node.name === 'option' || // TODO check it's actually bound
(element.node.name === 'input' &&
element.node.bindings.find(
(binding: Binding) =>
(binding) =>
/checked|group/.test(binding.name)
)));
@ -78,13 +81,13 @@ export default class AttributeWrapper {
// DRY it out if that's possible without introducing crazy indirection
if (this.node.chunks.length === 1) {
// single {tag} — may be a non-string
value = this.node.chunks[0].render(block);
value = (this.node.chunks[0] as Expression).render(block);
} else {
// '{foo} {bar}' — treat as string concatenation
value =
(this.node.chunks[0].type === 'Text' ? '' : `"" + `) +
this.node.chunks
.map((chunk: Node) => {
.map((chunk) => {
if (chunk.type === 'Text') {
return stringify(chunk.data);
} else {

@ -1,14 +1,15 @@
import Attribute from '../../../nodes/Attribute';
import Block from '../../Block';
import AttributeWrapper from './Attribute';
import Node from '../../../nodes/shared/Node';
import ElementWrapper from '.';
import { stringify } from '../../../utils/stringify';
import add_to_set from '../../../utils/add_to_set';
import Expression from '../../../nodes/shared/Expression';
import Text from '../../../nodes/Text';
export interface StyleProp {
key: string;
value: Node[];
value: (Text|Expression)[];
}
export default class StyleAttributeWrapper extends AttributeWrapper {
@ -28,7 +29,7 @@ export default class StyleAttributeWrapper extends AttributeWrapper {
value =
((prop.value.length === 1 || prop.value[0].type === 'Text') ? '' : `"" + `) +
prop.value
.map((chunk: Node) => {
.map((chunk) => {
if (chunk.type === 'Text') {
return stringify(chunk.data);
} else {
@ -54,7 +55,7 @@ export default class StyleAttributeWrapper extends AttributeWrapper {
);
}
} else {
value = stringify(prop.value[0].data);
value = stringify((prop.value[0] as Text).data);
}
block.builders.hydrate.add_line(
@ -64,8 +65,8 @@ export default class StyleAttributeWrapper extends AttributeWrapper {
}
}
function optimize_style(value: Node[]) {
const props: { key: string, value: Node[] }[] = [];
function optimize_style(value: (Text|Expression)[]) {
const props: StyleProp[] = [];
let chunks = value.slice();
while (chunks.length) {
@ -87,7 +88,7 @@ function optimize_style(value: Node[]) {
end: chunk.end,
type: 'Text',
data: remaining_data
};
} as Text;
} else {
chunks.shift();
}
@ -101,8 +102,8 @@ function optimize_style(value: Node[]) {
return props;
}
function get_style_value(chunks: Node[]) {
const value: Node[] = [];
function get_style_value(chunks: (Text | Expression)[]) {
const value: (Text|Expression)[] = [];
let in_url = false;
let quote_mark = null;
@ -141,7 +142,7 @@ function get_style_value(chunks: Node[]) {
start: chunk.start,
end: chunk.start + c,
data: chunk.data.slice(0, c)
});
} as Text);
}
while (/[;\s]/.test(chunk.data[c])) c += 1;
@ -153,7 +154,7 @@ function get_style_value(chunks: Node[]) {
end: chunk.end,
type: 'Text',
data: remaining_data
});
} as Text);
break;
}
@ -170,6 +171,6 @@ function get_style_value(chunks: Node[]) {
};
}
function is_dynamic(value: Node[]) {
function is_dynamic(value: (Text|Expression)[]) {
return value.length > 1 || value[0].type !== 'Text';
}

@ -20,20 +20,19 @@ import add_event_handlers from '../shared/add_event_handlers';
import add_actions from '../shared/add_actions';
import create_debugging_comment from '../shared/create_debugging_comment';
import { get_context_merger } from '../shared/get_context_merger';
import Slot from '../../../nodes/Slot';
const events = [
{
event_names: ['input'],
filter: (node: Element, name: string) =>
node.name === 'textarea' ||
node.name === 'input' && !/radio|checkbox|range/.test(node.get_static_attribute_value('type'))
node.name === 'input' && !/radio|checkbox|range/.test(node.get_static_attribute_value('type') as string)
},
{
event_names: ['change'],
filter: (node: Element, name: string) =>
node.name === 'select' ||
node.name === 'input' && /radio|checkbox/.test(node.get_static_attribute_value('type'))
node.name === 'input' && /radio|checkbox/.test(node.get_static_attribute_value('type') as string)
},
{
event_names: ['change', 'input'],
@ -135,7 +134,7 @@ export default class ElementWrapper extends Wrapper {
}
if (owner && owner.node.type === 'InlineComponent') {
const name = attribute.get_static_value();
const name = attribute.get_static_value() as string;
if (!(owner as InlineComponentWrapper).slots.has(name)) {
const child_block = block.child({
@ -275,6 +274,7 @@ export default class ElementWrapper extends Wrapper {
if (!this.node.namespace && this.can_use_innerhtml && this.fragment.nodes.length > 0) {
if (this.fragment.nodes.length === 1 && this.fragment.nodes[0].node.type === 'Text') {
block.builders.create.add_line(
// @ts-ignore todo: should it be this.fragment.nodes[0].node.data instead?
`${node}.textContent = ${stringify(this.fragment.nodes[0].data)};`
);
} else {
@ -324,7 +324,7 @@ export default class ElementWrapper extends Wrapper {
function to_html(wrapper: ElementWrapper | TextWrapper) {
if (wrapper.node.type === 'Text') {
const { parent } = wrapper.node;
const parent = wrapper.node.parent as Element;
const raw = parent && (
parent.name === 'script' ||
@ -349,7 +349,7 @@ export default class ElementWrapper extends Wrapper {
if (is_void(wrapper.node.name)) return open + '>';
return `${open}>${wrapper.fragment.nodes.map(to_html).join('')}</${wrapper.node.name}>`;
return `${open}>${(wrapper as ElementWrapper).fragment.nodes.map(to_html).join('')}</${wrapper.node.name}>`;
}
if (renderer.options.dev) {
@ -376,8 +376,8 @@ export default class ElementWrapper extends Wrapper {
get_claim_statement(nodes: string) {
const attributes = this.node.attributes
.filter((attr: Node) => attr.type === 'Attribute')
.map((attr: Node) => `${quote_name_if_necessary(attr.name)}: true`)
.filter((attr) => attr.type === 'Attribute')
.map((attr) => `${quote_name_if_necessary(attr.name)}: true`)
.join(', ');
const name = this.node.namespace
@ -553,12 +553,13 @@ export default class ElementWrapper extends Wrapper {
}
add_attributes(block: Block) {
// @ts-ignore todo:
if (this.node.attributes.find(attr => attr.type === 'Spread')) {
this.add_spread_attributes(block);
return;
}
this.attributes.forEach((attribute: Attribute) => {
this.attributes.forEach((attribute) => {
if (attribute.node.name === 'class' && attribute.node.is_dynamic) {
this.class_dependencies.push(...attribute.node.dependencies);
}
@ -814,27 +815,28 @@ export default class ElementWrapper extends Wrapper {
});
}
add_css_class(class_name = this.component.stylesheet.id) {
const class_attribute = this.attributes.find(a => a.name === 'class');
if (class_attribute && !class_attribute.is_true) {
if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
(class_attribute.chunks[0] as Text).data += ` ${class_name}`;
} else {
(class_attribute.chunks as Node[]).push(
new Text(this.component, this, this.scope, {
type: 'Text',
data: ` ${class_name}`
})
);
}
} else {
this.attributes.push(
new Attribute(this.component, this, this.scope, {
type: 'Attribute',
name: 'class',
value: [{ type: 'Text', data: class_name }]
})
);
}
}
// todo: looks to be dead code copypasted from Element.add_css_class in src/compile/nodes/Element.ts
// add_css_class(class_name = this.component.stylesheet.id) {
// const class_attribute = this.attributes.find(a => a.name === 'class');
// if (class_attribute && !class_attribute.is_true) {
// if (class_attribute.chunks.length === 1 && class_attribute.chunks[0].type === 'Text') {
// (class_attribute.chunks[0] as Text).data += ` ${class_name}`;
// } else {
// (class_attribute.chunks as Node[]).push(
// new Text(this.component, this, this.scope, {
// type: 'Text',
// data: ` ${class_name}`
// })
// );
// }
// } else {
// this.attributes.push(
// new Attribute(this.component, this, this.scope, {
// type: 'Attribute',
// name: 'class',
// value: [{ type: 'Text', data: class_name }]
// })
// );
// }
// }
}

@ -13,7 +13,7 @@ import Slot from './Slot';
import Text from './Text';
import Title from './Title';
import Window from './Window';
import Node from '../../nodes/shared/Node';
import { INode } from '../../nodes/interfaces';
import TextWrapper from './Text';
import Renderer from '../Renderer';
import Block from '../Block';
@ -49,7 +49,7 @@ export default class FragmentWrapper {
constructor(
renderer: Renderer,
block: Block,
nodes: Node[],
nodes: INode[],
parent: Wrapper,
strip_whitespace: boolean,
next_sibling: Wrapper
@ -85,6 +85,7 @@ export default class FragmentWrapper {
// *unless* there is no whitespace between this node and its next sibling
if (this.nodes.length === 0) {
const should_trim = (
// @ts-ignore todo:
next_sibling ? (next_sibling.node.type === 'Text' && /^\s/.test(next_sibling.data)) : !child.has_ancestor('EachBlock')
);
@ -96,6 +97,7 @@ export default class FragmentWrapper {
// glue text nodes (which could e.g. be separated by comments) together
if (last_child && last_child.node.type === 'Text') {
// @ts-ignore todo: probably error, should it be last_child.node.data?
last_child.data = data + last_child.data;
continue;
}

@ -96,7 +96,7 @@ export default class IfBlockWrapper extends Wrapper {
if (branch.block.has_outros) has_outros = true;
if (is_else_if(node.else)) {
create_branches(node.else.children[0]);
create_branches(node.else.children[0] as IfBlock);
} else if (node.else) {
const branch = new IfBlockBranch(
renderer,

@ -142,7 +142,7 @@ export default class InlineComponentWrapper extends Wrapper {
if (this.fragment) {
const default_slot = this.slots.get('default');
this.fragment.nodes.forEach((child: Wrapper) => {
this.fragment.nodes.forEach((child) => {
child.render(default_slot.block, null, 'nodes');
});
}

@ -1,13 +1,14 @@
import Renderer from '../Renderer';
import Block from '../Block';
import Node from '../../nodes/shared/Node';
import Tag from './shared/Tag';
import Wrapper from './shared/Wrapper';
import MustacheTag from '../../nodes/MustacheTag';
import RawMustacheTag from '../../nodes/RawMustacheTag';
export default class MustacheTagWrapper extends Tag {
var = 't';
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: Node) {
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: MustacheTag | RawMustacheTag) {
super(renderer, block, parent, node);
this.cannot_use_innerhtml();
}

@ -1,9 +1,10 @@
import Renderer from '../Renderer';
import Block from '../Block';
import Node from '../../nodes/shared/Node';
import Tag from './shared/Tag';
import Wrapper from './shared/wrapper';
import deindent from '../../utils/deindent';
import MustacheTag from '../../nodes/MustacheTag';
import RawMustacheTag from '../../nodes/RawMustacheTag';
export default class RawMustacheTagWrapper extends Tag {
var = 'raw';
@ -12,7 +13,7 @@ export default class RawMustacheTagWrapper extends Tag {
renderer: Renderer,
block: Block,
parent: Wrapper,
node: Node
node: MustacheTag | RawMustacheTag
) {
super(renderer, block, parent, node);
this.cannot_use_innerhtml();

@ -9,7 +9,6 @@ import add_to_set from '../../utils/add_to_set';
import get_slot_data from '../../utils/get_slot_data';
import { stringify_props } from '../../utils/stringify_props';
import Expression from '../../nodes/shared/Expression';
import Attribute from '../../nodes/Attribute';
export default class SlotWrapper extends Wrapper {
node: Slot;

@ -4,6 +4,7 @@ import Block from '../Block';
import Title from '../../nodes/Title';
import { stringify } from '../../utils/stringify';
import add_to_set from '../../utils/add_to_set';
import Text from '../../nodes/Text';
export default class TitleWrapper extends Wrapper {
node: Title;
@ -31,6 +32,7 @@ export default class TitleWrapper extends Wrapper {
// DRY it out if that's possible without introducing crazy indirection
if (this.node.children.length === 1) {
// single {tag} — may be a non-string
// @ts-ignore todo: check this
const { expression } = this.node.children[0];
value = expression.render(block);
add_to_set(all_dependencies, expression.dependencies);
@ -39,16 +41,18 @@ export default class TitleWrapper extends Wrapper {
value =
(this.node.children[0].type === 'Text' ? '' : `"" + `) +
this.node.children
.map((chunk: Node) => {
.map((chunk) => {
if (chunk.type === 'Text') {
return stringify(chunk.data);
} else {
// @ts-ignore todo: check this
const snippet = chunk.expression.render(block);
// @ts-ignore todo: check this
chunk.expression.dependencies.forEach(d => {
all_dependencies.add(d);
});
// @ts-ignore todo: check this
return chunk.expression.get_precedence() <= 13 ? `(${snippet})` : snippet;
}
})
@ -88,7 +92,7 @@ export default class TitleWrapper extends Wrapper {
);
}
} else {
const value = stringify(this.node.children[0].data);
const value = stringify((this.node.children[0] as Text).data);
block.builders.hydrate.add_line(`document.title = ${value};`);
}
}

@ -6,6 +6,7 @@ import deindent from '../../utils/deindent';
import add_event_handlers from './shared/add_event_handlers';
import Window from '../../nodes/Window';
import add_actions from './shared/add_actions';
import { INode } from '../../nodes/interfaces';
const associated_events = {
innerWidth: 'resize',
@ -33,7 +34,7 @@ const readonly = new Set([
export default class WindowWrapper extends Wrapper {
node: Window;
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: Node) {
constructor(renderer: Renderer, block: Block, parent: Wrapper, node: INode) {
super(renderer, block, parent, node);
}

@ -1,11 +1,11 @@
import Renderer from '../../Renderer';
import Node from '../../../nodes/shared/Node';
import Block from '../../Block';
import { INode } from '../../../nodes/interfaces';
export default class Wrapper {
renderer: Renderer;
parent: Wrapper;
node: Node;
node: INode;
prev: Wrapper | null;
next: Wrapper | null;
@ -17,7 +17,7 @@ export default class Wrapper {
renderer: Renderer,
block: Block,
parent: Wrapper,
node: Node
node: INode
) {
this.node = node;
@ -75,4 +75,8 @@ export default class Wrapper {
this.node.type === 'MustacheTag'
);
}
render(block: Block, parent_node: string, parent_nodes: string){
throw Error('Wrapper class is not renderable');
}
}

@ -1,8 +1,9 @@
import Component from '../../../Component';
import { Node } from '../../../../interfaces';
import { INode } from '../../../nodes/interfaces';
export default function create_debugging_comment(
node: Node,
node: INode,
component: Component
) {
const { locate, source } = component;
@ -19,6 +20,7 @@ export default function create_debugging_comment(
d = node.children.length ? node.children[0].start : node.start;
while (source[d - 1] !== '>') d -= 1;
} else {
// @ts-ignore
d = node.expression ? node.expression.node.end : c;
while (source[d] !== '}') d += 1;
while (source[d] === '}') d += 1;

@ -74,6 +74,7 @@ export default async function preprocess(
preprocessor: PreprocessorGroup | PreprocessorGroup[],
options?: { filename?: string }
) {
// @ts-ignore todo: doublecheck
const filename = (options && options.filename) || preprocessor.filename; // legacy
const dependencies = [];

Loading…
Cancel
Save