Convert src/compiler/compile/render_ssr/Renderer.ts to JavaScript

pull/8569/head
Simon Holthausen 3 years ago
parent 6f7d19c880
commit bedaf3b529

@ -1,129 +1,136 @@
import AwaitBlock from './handlers/AwaitBlock'; import AwaitBlock from './handlers/AwaitBlock.js';
import Comment from './handlers/Comment'; import Comment from './handlers/Comment.js';
import DebugTag from './handlers/DebugTag'; import DebugTag from './handlers/DebugTag.js';
import EachBlock from './handlers/EachBlock'; import EachBlock from './handlers/EachBlock.js';
import Element from './handlers/Element'; import Element from './handlers/Element.js';
import Head from './handlers/Head'; import Head from './handlers/Head.js';
import HtmlTag from './handlers/HtmlTag'; import HtmlTag from './handlers/HtmlTag.js';
import IfBlock from './handlers/IfBlock'; import IfBlock from './handlers/IfBlock.js';
import InlineComponent from './handlers/InlineComponent'; import InlineComponent from './handlers/InlineComponent.js';
import KeyBlock from './handlers/KeyBlock'; import KeyBlock from './handlers/KeyBlock.js';
import Slot from './handlers/Slot'; import Slot from './handlers/Slot.js';
import SlotTemplate from './handlers/SlotTemplate'; import SlotTemplate from './handlers/SlotTemplate.js';
import Tag from './handlers/Tag'; import Tag from './handlers/Tag.js';
import Text from './handlers/Text'; import Text from './handlers/Text.js';
import Title from './handlers/Title'; import Title from './handlers/Title.js';
import { AppendTarget, CompileOptions } from '../../interfaces'; import { collapse_template_literal } from '../utils/collapse_template_literal.js';
import { INode } from '../nodes/interfaces'; import { escape_template } from '../utils/stringify.js';
import { Expression, TemplateLiteral, Identifier } from 'estree'; function noop() { }
import { collapse_template_literal } from '../utils/collapse_template_literal';
import { escape_template } from '../utils/stringify'; /** @type {Record<string, Handler>} */
const handlers = {
type Handler = (node: any, renderer: Renderer, options: CompileOptions) => void; AwaitBlock,
Body: noop,
function noop() {} Comment,
DebugTag,
const handlers: Record<string, Handler> = { Document: noop,
AwaitBlock, EachBlock,
Body: noop, Element,
Comment, Head,
DebugTag, IfBlock,
Document: noop, InlineComponent,
EachBlock, KeyBlock,
Element, MustacheTag: Tag,
Head, Options: noop,
IfBlock, RawMustacheTag: HtmlTag,
InlineComponent, Slot,
KeyBlock, SlotTemplate,
MustacheTag: Tag, // TODO MustacheTag is an anachronism Text,
Options: noop, Title,
RawMustacheTag: HtmlTag, Window: noop
Slot,
SlotTemplate,
Text,
Title,
Window: noop
}; };
/** */
export interface RenderOptions extends CompileOptions {
locate: (c: number) => { line: number; column: number };
head_id?: string;
has_added_svelte_hash?: boolean;
}
export default class Renderer { export default class Renderer {
has_bindings = false;
name: Identifier;
stack: Array<{ current: { value: string }; literal: TemplateLiteral }> = [];
current: { value: string }; // TODO can it just be `current: string`?
literal: TemplateLiteral;
targets: AppendTarget[] = [];
constructor({ name }) {
this.name = name;
this.push();
}
add_string(str: string) {
this.current.value += escape_template(str);
}
add_expression(node: Expression) { /** @default false */
this.literal.quasis.push({ has_bindings = false;
type: 'TemplateElement',
value: { raw: this.current.value, cooked: null }, /** @type {import('estree').Identifier} */
tail: false name = undefined;
});
/**
this.literal.expressions.push(node); * @default []
this.current.value = ''; * @type {Array<{ current: { value: string }; literal: TemplateLiteral }>}
} */
stack = [];
push() {
const current = (this.current = { value: '' }); /** @type {{ value: string }} */
current = undefined; // TODO can it just be `current: string`?
const literal = (this.literal = {
type: 'TemplateLiteral', /** @type {import('estree').TemplateLiteral} */
expressions: [], literal = undefined;
quasis: []
}); /**
* @default []
this.stack.push({ current, literal }); * @type {AppendTarget[]}
} */
targets = [];
pop() { constructor({ name }) {
this.literal.quasis.push({ this.name = name;
type: 'TemplateElement', this.push();
value: { raw: this.current.value, cooked: null }, }
tail: true
}); /** @param {string} str */
add_string(str) {
const popped = this.stack.pop(); this.current.value += escape_template(str);
const last = this.stack[this.stack.length - 1]; }
if (last) { /** @param {import('estree').Expression} node */
this.literal = last.literal; add_expression(node) {
this.current = last.current; this.literal.quasis.push({
} type: 'TemplateElement',
value: { raw: this.current.value, cooked: null },
// Optimize the TemplateLiteral to remove unnecessary nodes tail: false
collapse_template_literal(popped.literal); });
this.literal.expressions.push(node);
return popped.literal; this.current.value = '';
} }
push() {
const current = (this.current = { value: '' });
const literal = (this.literal = {
type: 'TemplateLiteral',
expressions: [],
quasis: []
});
this.stack.push({ current, literal });
}
pop() {
this.literal.quasis.push({
type: 'TemplateElement',
value: { raw: this.current.value, cooked: null },
tail: true
});
const popped = this.stack.pop();
const last = this.stack[this.stack.length - 1];
if (last) {
this.literal = last.literal;
this.current = last.current;
}
// Optimize the TemplateLiteral to remove unnecessary nodes
collapse_template_literal(popped.literal);
return popped.literal;
}
/**
* @param {INode[]} nodes
* @param {RenderOptions} options
*/
render(nodes, options) {
nodes.forEach((node) => {
const handler = handlers[node.type];
if (!handler) {
throw new Error(`No handler for '${node.type}' nodes`);
}
handler(node, this, options);
});
}
}
render(nodes: INode[], options: RenderOptions) {
nodes.forEach((node) => {
const handler = handlers[node.type];
if (!handler) { /** @typedef {(node: any, renderer: Renderer, options: CompileOptions) => void} Handler */
throw new Error(`No handler for '${node.type}' nodes`);
}
handler(node, this, options); /** @typedef {Object} RenderOptions
}); * @property {(c:number)=>{line:number;column:number}} locate
} * @property {string} [head_id]
} * @property {boolean} [has_added_svelte_hash]
*/

@ -1,6 +1,6 @@
/** /**
* @param {Let[]} lets * @param {import('../../../nodes/Let.js').default[]} lets
* @returns {import("C:/repos/svelte/svelte/node_modules/.pnpm/@types+estree@1.0.0/node_modules/@types/estree/index").ObjectPattern} * @returns {import('estree').ObjectPattern}
*/ */
export function get_slot_scope(lets) { export function get_slot_scope(lets) {
if (lets.length === 0) return null; if (lets.length === 0) return null;

Loading…
Cancel
Save