diff --git a/src/compiler/HtmlJsParser.js b/src/compiler/HtmlJsParser.js
index 2a693d84d..c7cd0be33 100644
--- a/src/compiler/HtmlJsParser.js
+++ b/src/compiler/HtmlJsParser.js
@@ -30,7 +30,10 @@ class HtmlJsParser {
if (part.type === "placeholder") {
value += "${" + part.value + "}";
} else {
- value += part.replace(/`/g, "\\`");
+ value += part.replace(
+ /`|\\|\${/g,
+ match => "\\" + match
+ );
}
});
event.value = "$nonstandard`" + value + "`";
diff --git a/src/compiler/ast/HtmlElement/vdom/generateCode.js b/src/compiler/ast/HtmlElement/vdom/generateCode.js
index 2ad614731..be9529107 100644
--- a/src/compiler/ast/HtmlElement/vdom/generateCode.js
+++ b/src/compiler/ast/HtmlElement/vdom/generateCode.js
@@ -36,13 +36,19 @@ module.exports = function(node, codegen, vdomUtil) {
var body = codegen.generateCode(node.body);
var tagName = codegen.generateCode(node.tagNameExpression);
var attributes = codegen.generateCode(node.getAttributes());
- var properties = codegen.generateCode(node.getProperties());
var dynamicAttributes = codegen.generateCode(node.dynamicAttributes);
- var key = node.key;
+ var key = codegen.generateCode(node.key);
+ var properties = node.getProperties();
var isAutoKeyed = node.isAutoKeyed;
var runtimeFlags = node.runtimeFlags;
var nextConstId = node.nextConstId;
+ if (properties) {
+ Object.keys(properties).forEach(
+ key => (properties[key] = codegen.generateCode(properties[key]))
+ );
+ }
+
var builder = codegen.builder;
var isKeyStatic = vdomUtil.isStaticValue(key);
diff --git a/src/compiler/ast/TemplateLiteral.js b/src/compiler/ast/TemplateLiteral.js
index 5b585cf1e..bbf1b17a6 100644
--- a/src/compiler/ast/TemplateLiteral.js
+++ b/src/compiler/ast/TemplateLiteral.js
@@ -38,35 +38,39 @@ class TemplateLiteral extends Node {
}
writeCode(writer) {
- for (let i = 0; i <= this.quasis.length; i++) {
- const quasi = this.quasis[i];
- const expr = this.expressions[i];
- if (quasi || i === 0) {
- if (i > 0) writer.write("+");
- writer.write(JSON.stringify(quasi));
- }
- if (expr) {
- writer.write("+");
- writer.write("(");
- writer.write(expr);
- writer.write(")");
- }
- }
- writer.write("\n");
- }
-
- toString() {
let code = "";
let quote = this.nonstandard ? '"' : "`";
- let escape = new RegExp(quote, "g");
for (let i = 0; i <= this.quasis.length; i++) {
const quasi = this.quasis[i];
const expr = this.expressions[i];
- if (quasi) code += quasi.replace(escape, `\\${quote}`);
+ if (quasi) code += escapeQuasi(quasi, quote);
if (expr) code += "${" + expr.toString() + "}";
}
- return quote + code + quote;
+ writer.write(quote + code + quote);
+ writer.write("\n");
}
}
+function escapeQuasi(quasi, quote) {
+ if (!quasi) return "";
+ return quasi.replace(/["`\\\n\r\u2028\u2029]|\${/g, match => {
+ switch (match) {
+ case quote:
+ case "${":
+ case "\\":
+ return "\\" + match;
+ case "\n":
+ return "\\n";
+ case "\r":
+ return "\\r";
+ case "\u2028":
+ return "\\u2028";
+ case "\u2029":
+ return "\\u2029";
+ default:
+ return match;
+ }
+ });
+}
+
module.exports = TemplateLiteral;
diff --git a/src/taglibs/migrate/assign-tag.js b/src/taglibs/migrate/assign-tag.js
index 508adb9c0..e44499dc7 100644
--- a/src/taglibs/migrate/assign-tag.js
+++ b/src/taglibs/migrate/assign-tag.js
@@ -24,7 +24,12 @@ module.exports = function migrator(elNode, context) {
value:
attr.value == null
? attr.name
- : `${attr.name} = ${printJS(attr.value, context)}`
+ : `${attr.name} = ${printJS(
+ attr.value,
+ context,
+ null,
+ true
+ )}`
})
);
});
diff --git a/src/taglibs/migrate/util/printJS.js b/src/taglibs/migrate/util/printJS.js
index fee69b77e..d5e1a6f89 100644
--- a/src/taglibs/migrate/util/printJS.js
+++ b/src/taglibs/migrate/util/printJS.js
@@ -1,6 +1,9 @@
const CodeWriter = require("../../../compiler/CodeWriter");
+const CodeGenerator = require("../../../compiler/CodeGenerator");
module.exports = function(node, context, options) {
+ const codeGenerator = new CodeGenerator(context);
+ node = codeGenerator.generateCode(node);
const writer = new CodeWriter(
Object.assign({}, context.options, options),
context.builder
diff --git a/test/codegen/fixtures/templateLiteral/expected.js b/test/codegen/fixtures/templateLiteral/expected.js
new file mode 100644
index 000000000..47e06b67c
--- /dev/null
+++ b/test/codegen/fixtures/templateLiteral/expected.js
@@ -0,0 +1,8 @@
+`hello ${name}`
+`hello \${name}`
+`hello \\${name}`
+`hello "\`"`
+"hello ${name}"
+"hello \${name}"
+"hello \\${name}"
+"hello \"`\""
diff --git a/test/codegen/fixtures/templateLiteral/index.js b/test/codegen/fixtures/templateLiteral/index.js
new file mode 100644
index 000000000..b656d3a9d
--- /dev/null
+++ b/test/codegen/fixtures/templateLiteral/index.js
@@ -0,0 +1,52 @@
+"use strict";
+
+module.exports = function(builder) {
+ var templateLiteral = builder.templateLiteral(
+ ["hello ", ""],
+ [builder.identifier("name")]
+ );
+ var templateLiteralEscape = builder.templateLiteral(["hello ${name}"], []);
+ var templateLiteralEscape2 = builder.templateLiteral(
+ ["hello \\", ""],
+ [builder.identifier("name")]
+ );
+ var templateLiteralEscapeQuotes = builder.templateLiteral(
+ ['hello "`"'],
+ []
+ );
+
+ var nsTemplateLiteral = builder.templateLiteral(
+ ["hello ", ""],
+ [builder.identifier("name")]
+ );
+ var nsTemplateLiteralEscape = builder.templateLiteral(
+ ["hello ${name}"],
+ []
+ );
+ var nsTemplateLiteralEscape2 = builder.templateLiteral(
+ ["hello \\", ""],
+ [builder.identifier("name")]
+ );
+ var nsTemplateLiteralEscapeQuotes = builder.templateLiteral(
+ ['hello "`"'],
+ []
+ );
+
+ nsTemplateLiteral.nonstandard = true;
+ nsTemplateLiteralEscape.nonstandard = true;
+ nsTemplateLiteralEscape2.nonstandard = true;
+ nsTemplateLiteralEscapeQuotes.nonstandard = true;
+
+ return [
+ templateLiteral,
+ templateLiteralEscape,
+ templateLiteralEscape2,
+ templateLiteralEscapeQuotes,
+ nsTemplateLiteral,
+ nsTemplateLiteralEscape,
+ nsTemplateLiteralEscape2,
+ nsTemplateLiteralEscapeQuotes
+ ];
+};
+
+module.exports.skipCodegen = true;
diff --git a/test/codegen/index.test.js b/test/codegen/index.test.js
index 7bb7a6804..624752e6a 100644
--- a/test/codegen/index.test.js
+++ b/test/codegen/index.test.js
@@ -30,6 +30,7 @@ autotest("fixtures", fixture => {
test(done => {
var main = require(resolve("index.js"));
var generateCodeFunc = main;
+ var skipCodegen = main.skipCodegen === true;
var context = new CompileContext(
"dummy",
@@ -40,7 +41,7 @@ autotest("fixtures", fixture => {
var codeWriter = createCodeWriter(context);
var ast = generateCodeFunc(builder, codegen);
- var finalAST = codegen.generateCode(ast);
+ var finalAST = skipCodegen ? ast : codegen.generateCode(ast);
codeWriter.write(finalAST);