aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/js_ast.zig11
-rw-r--r--src/js_printer.zig10
-rw-r--r--test/bundler/bundler_string.test.ts52
3 files changed, 63 insertions, 10 deletions
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 58f5efae2..cdf7a3ad9 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -2176,7 +2176,7 @@ pub const E = struct {
return @ptrCast([*]const u16, @alignCast(@alignOf(u16), this.data.ptr))[0..this.data.len];
}
- pub fn resovleRopeIfNeeded(this: *String, allocator: std.mem.Allocator) void {
+ pub fn resolveRopeIfNeeded(this: *String, allocator: std.mem.Allocator) void {
if (this.next == null or !this.isUTF8()) return;
var str = this.next;
var bytes = std.ArrayList(u8).initCapacity(allocator, this.rope_len) catch unreachable;
@@ -2191,7 +2191,7 @@ pub const E = struct {
}
pub fn slice(this: *String, allocator: std.mem.Allocator) []const u8 {
- this.resovleRopeIfNeeded(allocator);
+ this.resolveRopeIfNeeded(allocator);
return this.string(allocator) catch unreachable;
}
@@ -2419,6 +2419,7 @@ pub const E = struct {
}
if (part.tail.len() > 0) {
+ head.data.e_string.resolveRopeIfNeeded(allocator);
head.data.e_string.push(Expr.init(E.String, part.tail, part.tail_loc).data.e_string);
}
@@ -2445,7 +2446,7 @@ pub const E = struct {
if (parts.items.len == 0) {
parts.deinit();
- head.data.e_string.resovleRopeIfNeeded(allocator);
+ head.data.e_string.resolveRopeIfNeeded(allocator);
return head;
}
@@ -5157,8 +5158,8 @@ pub const Expr = struct {
switch (right) {
.e_string => |r| {
equality.ok = true;
- r.resovleRopeIfNeeded(allocator);
- l.resovleRopeIfNeeded(allocator);
+ r.resolveRopeIfNeeded(allocator);
+ l.resolveRopeIfNeeded(allocator);
equality.equal = r.eql(E.String, l);
},
.e_null, .e_undefined => {
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 2a68135c1..e6d04a7c0 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -2507,7 +2507,7 @@ fn NewPrinter(
}
},
.e_string => |e| {
- e.resovleRopeIfNeeded(p.options.allocator);
+ e.resolveRopeIfNeeded(p.options.allocator);
p.addSourceMapping(expr.loc);
// If this was originally a template literal, print it as one as long as we're not minifying
@@ -2541,7 +2541,7 @@ fn NewPrinter(
p.print("`");
if (e.head.isPresent()) {
- e.head.resovleRopeIfNeeded(p.options.allocator);
+ e.head.resolveRopeIfNeeded(p.options.allocator);
p.printStringContent(&e.head, '`');
}
@@ -2551,7 +2551,7 @@ fn NewPrinter(
p.printExpr(part.value, .lowest, ExprFlag.None());
p.print("}");
if (part.tail.isPresent()) {
- part.tail.resovleRopeIfNeeded(p.options.allocator);
+ part.tail.resolveRopeIfNeeded(p.options.allocator);
p.printStringContent(&part.tail, '`');
}
}
@@ -3205,7 +3205,7 @@ fn NewPrinter(
.e_string => |key| {
p.addSourceMapping(_key.loc);
if (key.isUTF8()) {
- key.resovleRopeIfNeeded(p.options.allocator);
+ key.resolveRopeIfNeeded(p.options.allocator);
p.printSpaceBeforeIdentifier();
var allow_shorthand: bool = true;
// In react/cjs/react.development.js, there's part of a function like this:
@@ -3453,7 +3453,7 @@ fn NewPrinter(
switch (property.key.data) {
.e_string => |str| {
- str.resovleRopeIfNeeded(p.options.allocator);
+ str.resolveRopeIfNeeded(p.options.allocator);
p.addSourceMapping(property.key.loc);
if (str.isUTF8()) {
diff --git a/test/bundler/bundler_string.test.ts b/test/bundler/bundler_string.test.ts
index c70b83686..5a6861a05 100644
--- a/test/bundler/bundler_string.test.ts
+++ b/test/bundler/bundler_string.test.ts
@@ -134,4 +134,56 @@ describe("bundler", () => {
},
);
}
+
+ itBundled("string/TemplateFolding", {
+ files: {
+ "entry.js": /* js */ `
+ const s1 = "hello";
+ \`\${s1} world\`;
+ console.log(s1);
+
+ const s2 = \`hello\`;
+ console.log(s2);
+ const s3 = \`\${s2} world \${s1}\`;
+ console.log(s3);
+
+ const s4 = \`\${s1}\${s2}\${s3}\`;
+ console.log(s4);
+
+ const s5 = \`πŸ‘‹πŸŒŽ\`;
+ console.log(s5);
+ const s6 = \`\${s5} 🌍 \${s1}\`;
+ console.log(s6);
+
+ const s7 = \`\${s1}\${s2}\${s3}\${s4}\${s5}\${s6}\`;
+ console.log(s7);
+
+ const hexCharacters = "a-f\\d";
+ console.log(hexCharacters);
+ const match3or4Hex = \`#?[\${hexCharacters}]{3}[\${hexCharacters}]?\`;
+ console.log(match3or4Hex);
+ const match6or8Hex = \`#?[\${hexCharacters}]{6}([\${hexCharacters}]{2})?\`;
+ console.log(match6or8Hex);
+ const nonHexChars = new RegExp(\`[^#\${hexCharacters}]\`, "gi");
+ console.log(nonHexChars);
+ const validHexSize = new RegExp(\`^\${match3or4Hex}\$|^\${match6or8Hex}$\`, "i");
+ console.log(validHexSize);
+ `,
+ },
+ bundling: false,
+ run: {
+ stdout: `hello
+ hello
+ hello world hello
+ hellohellohello world hello
+ πŸ‘‹πŸŒŽ
+ πŸ‘‹πŸŒŽ 🌍 hello
+ hellohellohello world hellohellohellohello world helloπŸ‘‹πŸŒŽπŸ‘‹πŸŒŽ 🌍 hello
+ a-f\d
+ #?[a-f\d]{3}[a-f\d]?
+ #?[a-f\d]{6}([a-f\d]{2})?
+ /[^#a-f\d]/gi
+ /^#?[a-f\d]{3}[a-f\d]?$|^#?[a-f\d]{6}([a-f\d]{2})?$/i`,
+ },
+ });
});