simplify ssr

pull/1367/head
Rich Harris 7 years ago
parent 6cf3f1121f
commit 8759ccddbd

@ -220,21 +220,20 @@ export default class AwaitBlock extends Node {
});
}
ssr(compiler, block) {
ssr() {
const { compiler } = this;
const { snippet } = this.expression;
const childBlock = block.child({});
compiler.append('${(function(__value) { if(@isPromise(__value)) return `');
this.pending.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
compiler.append('`; return function(ctx) { return `');
this.then.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
compiler.append(`\`;}(Object.assign({}, ctx, { ${this.value}: __value }));}(${snippet})) }`);

@ -9,10 +9,10 @@ export default class Comment extends Node {
this.data = info.data;
}
ssr(compiler) {
ssr() {
// Allow option to preserve comments, otherwise ignore
if (compiler.options.preserveComments) {
compiler.append(`<!--${this.data}-->`);
if (this.compiler.options.preserveComments) {
this.compiler.append(`<!--${this.data}-->`);
}
}
}

@ -15,7 +15,7 @@ import mapChildren from './shared/mapChildren';
import Binding from './Binding';
import EventHandler from './EventHandler';
import Expression from './shared/Expression';
import { AppendTarget } from '../server-side-rendering/interfaces';
import { AppendTarget } from '../../interfaces';
export default class Component extends Node {
type: 'Component';
@ -483,7 +483,7 @@ export default class Component extends Node {
return `${this.var}._mount(${name}._slotted.default, null);`;
}
ssr(compiler, block) {
ssr() {
function stringifyAttribute(chunk: Node) {
if (chunk.type === 'Text') {
return escapeTemplate(escape(chunk.data));
@ -540,13 +540,35 @@ export default class Component extends Node {
const isDynamicComponent = this.name === 'svelte:component';
const expression = (
this.name === 'svelte:self' ? compiler.name :
this.name === 'svelte:self' ? this.compiler.name :
isDynamicComponent ? `((${this.expression.snippet}) || @missingComponent)` :
`%components-${this.name}`
);
this.bindings.forEach(binding => {
block.addBinding(binding, expression);
const conditions = [];
let node = this;
while (node = node.parent) {
if (node.type === 'IfBlock') {
// TODO handle contextual bindings...
conditions.push(`(${node.expression.snippet})`);
}
}
conditions.push(`!('${binding.name}' in ctx)`);
const { name } = getObject(binding.value.node);
this.compiler.bindings.push(deindent`
if (${conditions.reverse().join('&&')}) {
tmp = ${expression}.data();
if ('${name}' in tmp) {
ctx.${binding.name} = tmp.${name};
settled = false;
}
}
`);
});
let open = `\${${expression}._render(__result, ${props}`;
@ -560,10 +582,10 @@ export default class Component extends Node {
slotStack: ['default']
};
compiler.appendTargets.push(appendTarget);
this.compiler.appendTargets.push(appendTarget);
this.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
const slotted = Object.keys(appendTarget.slots)
@ -572,15 +594,15 @@ export default class Component extends Node {
options.push(`slotted: { ${slotted} }`);
compiler.appendTargets.pop();
this.compiler.appendTargets.pop();
}
if (options.length) {
open += `, { ${options.join(', ')} }`;
}
compiler.append(open);
compiler.append(')}');
this.compiler.append(open);
this.compiler.append(')}');
}
}

@ -473,7 +473,8 @@ export default class EachBlock extends Node {
return `for (var #i = 0; #i < ${this.iterations}.length; #i += 1) ${this.iterations}[#i].m(${name}._slotted.default, null);`;
}
ssr(compiler, block) {
ssr() {
const { compiler } = this;
const { snippet } = this.expression;
const props = [`${this.context}: item`]
@ -486,10 +487,8 @@ export default class EachBlock extends Node {
const open = `\${ ${this.else ? `${snippet}.length ? ` : ''}@each(${snippet}, ${getContext}, ctx => \``;
compiler.append(open);
const childBlock = block.child({});
this.children.forEach((child: Node) => {
child.ssr(compiler, childBlock);
child.ssr();
});
const close = `\`)`;
@ -498,7 +497,7 @@ export default class EachBlock extends Node {
if (this.else) {
compiler.append(` : \``);
this.else.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
compiler.append(`\``);
}

@ -831,7 +831,9 @@ export default class Element extends Node {
}
}
ssr(compiler, block) {
ssr() {
const { compiler } = this;
let openingTag = `<${this.name}`;
let textareaContents; // awkward special case
@ -902,7 +904,7 @@ export default class Element extends Node {
compiler.append(textareaContents);
} else {
this.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
}

@ -36,13 +36,13 @@ export default class Head extends Node {
});
}
ssr(compiler, block) {
compiler.append('${(__result.head += `');
ssr() {
this.compiler.append('${(__result.head += `');
this.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
compiler.append('`, "")}');
this.compiler.append('`, "")}');
}
}

@ -476,24 +476,21 @@ export default class IfBlock extends Node {
return branches;
}
ssr(compiler, block) {
ssr() {
const { compiler } = this;
const { snippet } = this.expression;
compiler.append('${ ' + snippet + ' ? `');
const childBlock = block.child({
conditions: block.conditions.concat(snippet),
});
this.children.forEach((child: Node) => {
child.ssr(compiler, childBlock);
child.ssr();
});
compiler.append('` : `');
if (this.else) {
this.else.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
}

@ -25,8 +25,8 @@ export default class MustacheTag extends Tag {
return `@appendNode(${this.var}, ${name}._slotted.default);`;
}
ssr(compiler) {
compiler.append(
ssr() {
this.compiler.append(
this.parent &&
this.parent.type === 'Element' &&
this.parent.name === 'style'

@ -88,7 +88,7 @@ export default class RawMustacheTag extends Tag {
return `@appendNode(${this.var}, ${name}._slotted.default);`;
}
ssr(compiler) {
compiler.append('${' + this.expression.snippet + '}');
ssr() {
this.compiler.append('${' + this.expression.snippet + '}');
}
}

@ -151,16 +151,16 @@ export default class Slot extends Element {
return null;
}
ssr(compiler, block) {
ssr() {
const name = this.attributes.find(attribute => attribute.name === 'name');
const slotName = name && name.chunks[0].data || 'default';
compiler.append(`\${options && options.slotted && options.slotted.${slotName} ? options.slotted.${slotName}() : \``);
this.compiler.append(`\${options && options.slotted && options.slotted.${slotName} ? options.slotted.${slotName}() : \``);
this.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
compiler.append(`\`}`);
this.compiler.append(`\`}`);
}
}

@ -68,7 +68,7 @@ export default class Text extends Node {
return `@appendNode(${this.var}, ${name}._slotted.default);`;
}
ssr(compiler) {
ssr() {
let text = this.data;
if (
!this.parent ||
@ -78,6 +78,6 @@ export default class Text extends Node {
// unless this Text node is inside a <script> or <style> element, escape &,<,>
text = escapeHTML(text);
}
compiler.append(escape(escapeTemplate(text)));
this.compiler.append(escape(escapeTemplate(text)));
}
}

@ -102,13 +102,13 @@ export default class Title extends Node {
}
}
ssr(compiler, block) {
compiler.append(`<title>`);
ssr() {
this.compiler.append(`<title>`);
this.children.forEach((child: Node) => {
child.ssr(compiler, block);
child.ssr();
});
compiler.append(`</title>`);
this.compiler.append(`</title>`);
}
}

@ -1,41 +0,0 @@
import deindent from '../../utils/deindent';
import flattenReference from '../../utils/flattenReference';
import { SsrGenerator } from './index';
import { Node } from '../../interfaces';
import getObject from '../../utils/getObject';
interface BlockOptions {
// TODO
}
export default class Block {
generator: SsrGenerator;
conditions: string[];
constructor(options: BlockOptions) {
Object.assign(this, options);
}
addBinding(binding: Node, name: string) {
const conditions = [`!('${binding.name}' in ctx)`].concat(
// TODO handle contextual bindings...
this.conditions.map(c => `(${c})`)
);
const { name: prop } = getObject(binding.value.node);
this.generator.bindings.push(deindent`
if (${conditions.join('&&')}) {
tmp = ${name}.data();
if ('${prop}' in tmp) {
ctx.${binding.name} = tmp.${prop};
settled = false;
}
}
`);
}
child(options: BlockOptions) {
return new Block(Object.assign({}, this, options, { parent: this }));
}
}

@ -2,13 +2,12 @@ import deindent from '../../utils/deindent';
import Generator from '../Generator';
import Stats from '../../Stats';
import Stylesheet from '../../css/Stylesheet';
import Block from './Block';
import visit from './visit';
import { removeNode, removeObjectKey } from '../../utils/removeNode';
import getName from '../../utils/getName';
import globalWhitelist from '../../utils/globalWhitelist';
import { Ast, Node, CompileOptions } from '../../interfaces';
import { AppendTarget } from './interfaces';
import { AppendTarget } from '../../interfaces';
import { stringify } from '../../utils/stringify';
export class SsrGenerator extends Generator {
@ -57,13 +56,8 @@ export default function ssr(
const { computations, name, templateProperties } = generator;
// create main render() function
const mainBlock = new Block({
generator,
conditions: [],
});
trim(generator.fragment.children).forEach((node: Node) => {
node.ssr(generator, mainBlock);
node.ssr();
});
const css = generator.customElement ?

@ -1,14 +0,0 @@
import { SsrGenerator } from './index';
import Block from './Block';
import { Node } from '../../interfaces';
export type Visitor = (
generator: SsrGenerator,
block: Block,
node: Node
) => void;
export interface AppendTarget {
slots: Record<string, string>;
slotStack: string[]
}

@ -97,3 +97,8 @@ export interface PreprocessOptions {
}
export type Preprocessor = (options: {content: string, attributes: Record<string, string | boolean>, filename?: string}) => { code: string, map?: SourceMap | string };
export interface AppendTarget {
slots: Record<string, string>;
slotStack: string[]
}
Loading…
Cancel
Save