Merge pull request #860 from sveltejs/gh-23

use textContent and innerHTML where appropriate
pull/867/head
Rich Harris 7 years ago committed by GitHub
commit 9f4db8dc04

@ -41,6 +41,13 @@ function createDebuggingComment(node: Node, generator: DomGenerator) {
return `${loc} ${source.slice(c, d)}`.replace(/\n/g, ' ');
}
function cannotUseInnerHTML(node: Node) {
while (node && node.canUseInnerHTML) {
node.canUseInnerHTML = false;
node = node.parent;
}
}
// Whitespace inside one of these elements will not result in
// a whitespace node being created in any circumstances. (This
// list is almost certainly very incomplete)
@ -65,6 +72,7 @@ const preprocessors = {
componentStack: Node[],
stripWhitespace: boolean
) => {
cannotUseInnerHTML(node);
node.var = block.getUniqueName('text');
const dependencies = block.findDependencies(node.expression);
@ -80,6 +88,7 @@ const preprocessors = {
componentStack: Node[],
stripWhitespace: boolean
) => {
cannotUseInnerHTML(node);
node.var = block.getUniqueName('raw');
const dependencies = block.findDependencies(node.expression);
@ -114,6 +123,8 @@ const preprocessors = {
stripWhitespace: boolean,
nextSibling: Node
) => {
cannotUseInnerHTML(node);
const blocks: Block[] = [];
let dynamic = false;
let hasIntros = false;
@ -195,6 +206,7 @@ const preprocessors = {
stripWhitespace: boolean,
nextSibling: Node
) => {
cannotUseInnerHTML(node);
node.var = block.getUniqueName(`each`);
const dependencies = block.findDependencies(node.expression);
@ -290,10 +302,16 @@ const preprocessors = {
stripWhitespace: boolean,
nextSibling: Node
) => {
if (node.name === 'slot') {
cannotUseInnerHTML(node);
}
node.attributes.forEach((attribute: Node) => {
if (attribute.type === 'Attribute' && attribute.value !== true) {
attribute.value.forEach((chunk: Node) => {
if (chunk.type !== 'Text') {
if (node.parent) cannotUseInnerHTML(node.parent);
const dependencies = block.findDependencies(chunk.expression);
block.addDependencies(dependencies);
@ -311,20 +329,24 @@ const preprocessors = {
}
}
});
} else if (attribute.type === 'EventHandler' && attribute.expression) {
attribute.expression.arguments.forEach((arg: Node) => {
const dependencies = block.findDependencies(arg);
} else {
if (node.parent) cannotUseInnerHTML(node.parent);
if (attribute.type === 'EventHandler' && attribute.expression) {
attribute.expression.arguments.forEach((arg: Node) => {
const dependencies = block.findDependencies(arg);
block.addDependencies(dependencies);
});
} else if (attribute.type === 'Binding') {
const dependencies = block.findDependencies(attribute.value);
block.addDependencies(dependencies);
});
} else if (attribute.type === 'Binding') {
const dependencies = block.findDependencies(attribute.value);
block.addDependencies(dependencies);
} else if (attribute.type === 'Transition') {
if (attribute.intro)
generator.hasIntroTransitions = block.hasIntroMethod = true;
if (attribute.outro) {
generator.hasOutroTransitions = block.hasOutroMethod = true;
block.outros += 1;
} else if (attribute.type === 'Transition') {
if (attribute.intro)
generator.hasIntroTransitions = block.hasIntroMethod = true;
if (attribute.outro) {
generator.hasOutroTransitions = block.hasOutroMethod = true;
block.outros += 1;
}
}
}
});
@ -340,6 +362,8 @@ const preprocessors = {
// so that if `foo.qux` changes, we know that we need to
// mark `bar` and `baz` as dirty too
if (node.name === 'select') {
cannotUseInnerHTML(node);
const value = node.attributes.find(
(attribute: Node) => attribute.name === 'value'
);
@ -359,6 +383,8 @@ const preprocessors = {
generator.components.has(node.name) || node.name === ':Self';
if (isComponent) {
cannotUseInnerHTML(node);
node.var = block.getUniqueName(
(node.name === ':Self' ? generator.name : node.name).toLowerCase()
);
@ -369,6 +395,7 @@ const preprocessors = {
} else {
const slot = getStaticAttributeValue(node, 'slot');
if (slot && isChildOfComponent(node, generator)) {
cannotUseInnerHTML(node);
node.slotted = true;
// TODO validate slots — no nesting, no dynamic names...
const component = componentStack[componentStack.length - 1];
@ -442,6 +469,7 @@ function preprocessChildren(
cleaned.forEach((child: Node, i: number) => {
child.parent = node;
child.canUseInnerHTML = !generator.hydratable;
const preprocessor = preprocessors[child.type];
if (preprocessor) preprocessor(generator, block, state, child, inEachBlock, elementStack, componentStack, stripWhitespace, cleaned[i + 1] || nextSibling);

@ -9,6 +9,7 @@ import visitBinding from './Binding';
import visitRef from './Ref';
import * as namespaces from '../../../../utils/namespaces';
import getStaticAttributeValue from '../../../../utils/getStaticAttributeValue';
import isVoidElementName from '../../../../utils/isVoidElementName';
import addTransitions from './addTransitions';
import { DomGenerator } from '../../index';
import Block from '../../Block';
@ -94,7 +95,6 @@ export default function visitElement(
}
// add CSS encapsulation attribute
// TODO add a helper for this, rather than repeating it
if (node._needsCssAttribute && !generator.customElement) {
generator.needsEncapsulateHelper = true;
block.builders.hydrate.addLine(
@ -202,9 +202,21 @@ export default function visitElement(
node.initialUpdate = node.lateUpdate = statement;
}
node.children.forEach((child: Node) => {
visit(generator, block, childState, child, elementStack.concat(node), componentStack);
});
if (!childState.namespace && node.canUseInnerHTML && node.children.length > 0) {
if (node.children.length === 1 && node.children[0].type === 'Text') {
block.builders.create.addLine(
`${name}.textContent = ${JSON.stringify(node.children[0].data)};`
);
} else {
block.builders.create.addLine(
`${name}.innerHTML = ${JSON.stringify(node.children.map(toHTML).join(''))};`
);
}
} else {
node.children.forEach((child: Node) => {
visit(generator, block, childState, child, elementStack.concat(node), componentStack);
});
}
if (node.lateUpdate) {
block.builders.update.addLine(node.lateUpdate);
@ -221,6 +233,29 @@ export default function visitElement(
block.builders.claim.addLine(
`${childState.parentNodes}.forEach(@detachNode);`
);
function toHTML(node: Node) {
if (node.type === 'Text') return node.data;
let open = `<${node.name}`;
if (node._needsCssAttribute) {
open += ` ${generator.stylesheet.id}`;
}
if (node._cssRefAttribute) {
open += ` svelte-ref-${node._cssRefAttribute}`;
}
node.attributes.forEach((attr: Node) => {
open += ` ${attr.name}${stringifyAttributeValue(attr.value)}`
});
if (isVoidElementName(node.name)) return open + '>';
if (node.children.length === 0) return open + '/>';
return `${open}>${node.children.map(toHTML).join('')}</${node.name}>`;
}
}
function getRenderStatement(
@ -263,3 +298,11 @@ function quoteProp(name: string, legacy: boolean) {
if (/[^a-zA-Z_$0-9]/.test(name) || isLegacyPropName) return `"${name}"`;
return name;
}
function stringifyAttributeValue(value: Node | true) {
if (value === true) return '';
if (value.length === 0) return `=""`;
const data = value[0].data;
return `=${JSON.stringify(data)}`;
}

@ -13,10 +13,6 @@ function assign(target) {
return target;
}
function appendNode(node, target) {
target.appendChild(node);
}
function insertNode(node, target, anchor) {
target.insertBefore(node, anchor);
}
@ -29,10 +25,6 @@ function createElement(name) {
return document.createElement(name);
}
function createText(data) {
return document.createTextNode(data);
}
function blankObject() {
return Object.create(null);
}
@ -187,17 +179,16 @@ var proto = {
/* generated by Svelte vX.Y.Z */
function create_main_fragment(state, component) {
var div, text;
var div;
return {
create: function() {
div = createElement("div");
text = createText("fades in");
div.textContent = "fades in";
},
mount: function(target, anchor) {
insertNode(div, target, anchor);
appendNode(text, div);
},
update: noop,

@ -1,18 +1,17 @@
/* generated by Svelte vX.Y.Z */
import { appendNode, assign, createElement, createText, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
import { assign, createElement, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
function create_main_fragment(state, component) {
var div, text;
var div;
return {
create: function() {
div = createElement("div");
text = createText("fades in");
div.textContent = "fades in";
},
mount: function(target, anchor) {
insertNode(div, target, anchor);
appendNode(text, div);
},
update: noop,

@ -13,10 +13,6 @@ function assign(target) {
return target;
}
function appendNode(node, target) {
target.appendChild(node);
}
function insertNode(node, target, anchor) {
target.insertBefore(node, anchor);
}
@ -29,10 +25,6 @@ function createElement(name) {
return document.createElement(name);
}
function createText(data) {
return document.createTextNode(data);
}
function blankObject() {
return Object.create(null);
}
@ -202,12 +194,12 @@ var template = (function() {
}());
function create_main_fragment(state, component) {
var button, foo_handler, text;
var button, foo_handler;
return {
create: function() {
button = createElement("button");
text = createText("foo");
button.textContent = "foo";
this.hydrate();
},
@ -220,7 +212,6 @@ function create_main_fragment(state, component) {
mount: function(target, anchor) {
insertNode(button, target, anchor);
appendNode(text, button);
},
update: noop,

@ -1,5 +1,5 @@
/* generated by Svelte vX.Y.Z */
import { appendNode, assign, createElement, createText, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
import { assign, createElement, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
var template = (function() {
return {
@ -17,12 +17,12 @@ var template = (function() {
}());
function create_main_fragment(state, component) {
var button, foo_handler, text;
var button, foo_handler;
return {
create: function() {
button = createElement("button");
text = createText("foo");
button.textContent = "foo";
this.hydrate();
},
@ -35,7 +35,6 @@ function create_main_fragment(state, component) {
mount: function(target, anchor) {
insertNode(button, target, anchor);
appendNode(text, button);
},
update: noop,

@ -13,10 +13,6 @@ function assign(target) {
return target;
}
function appendNode(node, target) {
target.appendChild(node);
}
function insertNode(node, target, anchor) {
target.insertBefore(node, anchor);
}
@ -29,10 +25,6 @@ function createElement(name) {
return document.createElement(name);
}
function createText(data) {
return document.createTextNode(data);
}
function createComment() {
return document.createComment('');
}
@ -230,17 +222,16 @@ function create_main_fragment(state, component) {
// (1:0) {{#if foo}}
function create_if_block(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("foo!");
p.textContent = "foo!";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -253,17 +244,16 @@ function create_if_block(state, component) {
// (3:0) {{else}}
function create_if_block_1(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("not foo!");
p.textContent = "not foo!";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {

@ -1,5 +1,5 @@
/* generated by Svelte vX.Y.Z */
import { appendNode, assign, createComment, createElement, createText, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
import { assign, createComment, createElement, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
function create_main_fragment(state, component) {
var if_block_anchor;
@ -41,17 +41,16 @@ function create_main_fragment(state, component) {
// (1:0) {{#if foo}}
function create_if_block(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("foo!");
p.textContent = "foo!";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -64,17 +63,16 @@ function create_if_block(state, component) {
// (3:0) {{else}}
function create_if_block_1(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("not foo!");
p.textContent = "not foo!";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {

@ -13,10 +13,6 @@ function assign(target) {
return target;
}
function appendNode(node, target) {
target.appendChild(node);
}
function insertNode(node, target, anchor) {
target.insertBefore(node, anchor);
}
@ -29,10 +25,6 @@ function createElement(name) {
return document.createElement(name);
}
function createText(data) {
return document.createTextNode(data);
}
function createComment() {
return document.createComment('');
}
@ -233,17 +225,16 @@ function create_main_fragment(state, component) {
// (1:0) {{#if foo}}
function create_if_block(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("foo!");
p.textContent = "foo!";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {

@ -1,5 +1,5 @@
/* generated by Svelte vX.Y.Z */
import { appendNode, assign, createComment, createElement, createText, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
import { assign, createComment, createElement, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
function create_main_fragment(state, component) {
var if_block_anchor;
@ -44,17 +44,16 @@ function create_main_fragment(state, component) {
// (1:0) {{#if foo}}
function create_if_block(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("foo!");
p.textContent = "foo!";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {

@ -191,7 +191,7 @@ var proto = {
/* generated by Svelte vX.Y.Z */
function create_main_fragment(state, component) {
var div, text, p, text_1, text_2, text_3, text_4, p_1, text_5, text_6, text_8, if_block_4_anchor;
var div, text, p, text_2, text_3, text_4, p_1, text_6, text_8, if_block_4_anchor;
var if_block = (state.a) && create_if_block(state, component);
@ -209,14 +209,14 @@ function create_main_fragment(state, component) {
if (if_block) if_block.create();
text = createText("\n\n\t");
p = createElement("p");
text_1 = createText("this can be used as an anchor");
p.textContent = "this can be used as an anchor";
text_2 = createText("\n\n\t");
if (if_block_1) if_block_1.create();
text_3 = createText("\n\n\t");
if (if_block_2) if_block_2.create();
text_4 = createText("\n\n\t");
p_1 = createElement("p");
text_5 = createText("so can this");
p_1.textContent = "so can this";
text_6 = createText("\n\n\t");
if (if_block_3) if_block_3.create();
text_8 = createText("\n\n");
@ -229,14 +229,12 @@ function create_main_fragment(state, component) {
if (if_block) if_block.mount(div, null);
appendNode(text, div);
appendNode(p, div);
appendNode(text_1, p);
appendNode(text_2, div);
if (if_block_1) if_block_1.mount(div, null);
appendNode(text_3, div);
if (if_block_2) if_block_2.mount(div, null);
appendNode(text_4, div);
appendNode(p_1, div);
appendNode(text_5, p_1);
appendNode(text_6, div);
if (if_block_3) if_block_3.mount(div, null);
insertNode(text_8, target, anchor);
@ -329,17 +327,16 @@ function create_main_fragment(state, component) {
// (2:1) {{#if a}}
function create_if_block(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("a");
p.textContent = "a";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -352,17 +349,16 @@ function create_if_block(state, component) {
// (8:1) {{#if b}}
function create_if_block_1(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("b");
p.textContent = "b";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -375,17 +371,16 @@ function create_if_block_1(state, component) {
// (12:1) {{#if c}}
function create_if_block_2(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("c");
p.textContent = "c";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -398,17 +393,16 @@ function create_if_block_2(state, component) {
// (18:1) {{#if d}}
function create_if_block_3(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("d");
p.textContent = "d";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -421,17 +415,16 @@ function create_if_block_3(state, component) {
// (25:0) {{#if e}}
function create_if_block_4(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("e");
p.textContent = "e";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {

@ -2,7 +2,7 @@
import { appendNode, assign, createComment, createElement, createText, detachNode, init, insertNode, noop, proto } from "svelte/shared.js";
function create_main_fragment(state, component) {
var div, text, p, text_1, text_2, text_3, text_4, p_1, text_5, text_6, text_8, if_block_4_anchor;
var div, text, p, text_2, text_3, text_4, p_1, text_6, text_8, if_block_4_anchor;
var if_block = (state.a) && create_if_block(state, component);
@ -20,14 +20,14 @@ function create_main_fragment(state, component) {
if (if_block) if_block.create();
text = createText("\n\n\t");
p = createElement("p");
text_1 = createText("this can be used as an anchor");
p.textContent = "this can be used as an anchor";
text_2 = createText("\n\n\t");
if (if_block_1) if_block_1.create();
text_3 = createText("\n\n\t");
if (if_block_2) if_block_2.create();
text_4 = createText("\n\n\t");
p_1 = createElement("p");
text_5 = createText("so can this");
p_1.textContent = "so can this";
text_6 = createText("\n\n\t");
if (if_block_3) if_block_3.create();
text_8 = createText("\n\n");
@ -40,14 +40,12 @@ function create_main_fragment(state, component) {
if (if_block) if_block.mount(div, null);
appendNode(text, div);
appendNode(p, div);
appendNode(text_1, p);
appendNode(text_2, div);
if (if_block_1) if_block_1.mount(div, null);
appendNode(text_3, div);
if (if_block_2) if_block_2.mount(div, null);
appendNode(text_4, div);
appendNode(p_1, div);
appendNode(text_5, p_1);
appendNode(text_6, div);
if (if_block_3) if_block_3.mount(div, null);
insertNode(text_8, target, anchor);
@ -140,17 +138,16 @@ function create_main_fragment(state, component) {
// (2:1) {{#if a}}
function create_if_block(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("a");
p.textContent = "a";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -163,17 +160,16 @@ function create_if_block(state, component) {
// (8:1) {{#if b}}
function create_if_block_1(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("b");
p.textContent = "b";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -186,17 +182,16 @@ function create_if_block_1(state, component) {
// (12:1) {{#if c}}
function create_if_block_2(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("c");
p.textContent = "c";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -209,17 +204,16 @@ function create_if_block_2(state, component) {
// (18:1) {{#if d}}
function create_if_block_3(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("d");
p.textContent = "d";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {
@ -232,17 +226,16 @@ function create_if_block_3(state, component) {
// (25:0) {{#if e}}
function create_if_block_4(state, component) {
var p, text;
var p;
return {
create: function() {
p = createElement("p");
text = createText("e");
p.textContent = "e";
},
mount: function(target, anchor) {
insertNode(p, target, anchor);
appendNode(text, p);
},
unmount: function() {

Loading…
Cancel
Save