mirror of
https://github.com/oven-sh/bun
synced 2026-02-09 10:28:47 +00:00
allow template literals in bun macros
This commit is contained in:
@@ -579,8 +579,55 @@ pub const Runner = struct {
|
||||
out.* = value;
|
||||
}
|
||||
},
|
||||
.e_template => {
|
||||
@panic("TODO: support template literals in macros");
|
||||
.e_template => |template| {
|
||||
// For tagged template literals, the first argument is an array of template strings
|
||||
// followed by the interpolated values as separate arguments
|
||||
const parts_count = template.parts.len;
|
||||
const total_args = 1 + parts_count + @as(usize, @intFromBool(javascript_object != .zero));
|
||||
js_args = try allocator.alloc(jsc.JSValue, total_args);
|
||||
js_processed_args_len = total_args;
|
||||
|
||||
var template_strings = try allocator.alloc(jsc.JSValue, parts_count + 1);
|
||||
defer allocator.free(template_strings);
|
||||
|
||||
var head_str = switch (template.head) {
|
||||
.cooked => |str| str,
|
||||
.raw => |raw| E.String.init(raw),
|
||||
};
|
||||
template_strings[0] = try head_str.toJS(allocator, globalObject);
|
||||
template_strings[0].protect();
|
||||
|
||||
for (template.parts, 1..) |part, i| {
|
||||
var tail_str = switch (part.tail) {
|
||||
.cooked => |str| str,
|
||||
.raw => |raw| E.String.init(raw),
|
||||
};
|
||||
template_strings[i] = try tail_str.toJS(allocator, globalObject);
|
||||
template_strings[i].protect();
|
||||
}
|
||||
|
||||
js_args[0] = try jsc.JSArray.create(globalObject, template_strings);
|
||||
js_args[0].protect();
|
||||
|
||||
for (template_strings) |str| {
|
||||
str.unprotect();
|
||||
}
|
||||
|
||||
for (template.parts, 0..) |part, i| {
|
||||
const expr = part.value;
|
||||
const value = expr.toJS(
|
||||
allocator,
|
||||
globalObject,
|
||||
) catch |e| {
|
||||
for (js_args[0 .. i + 1]) |arg| {
|
||||
arg.unprotect();
|
||||
}
|
||||
js_processed_args_len = i + 1;
|
||||
return e;
|
||||
};
|
||||
value.protect();
|
||||
js_args[i + 1] = value;
|
||||
}
|
||||
},
|
||||
else => {
|
||||
@panic("Unexpected caller type");
|
||||
|
||||
@@ -9,6 +9,9 @@ import defaultMacro, {
|
||||
identity as identity1,
|
||||
identity as identity2,
|
||||
ireturnapromise,
|
||||
simpleTag,
|
||||
interpolateTag,
|
||||
objectTag,
|
||||
} from "./macro.ts" assert { type: "macro" };
|
||||
|
||||
import * as macros from "./macro.ts" assert { type: "macro" };
|
||||
@@ -118,6 +121,15 @@ test("namespace import", () => {
|
||||
expect(macros.escape()).toBe("\\\f\n\r\t\v\0'\"`$\x00\x0B\x0C");
|
||||
});
|
||||
|
||||
test("varables", () => {
|
||||
const a = "A";
|
||||
expect(identity(a)).toBe("A");
|
||||
});
|
||||
|
||||
test("template string basic", () => {
|
||||
expect(identity(`A`)).toBe("A");
|
||||
});
|
||||
|
||||
// test("template string ascii", () => {
|
||||
// expect(identity(`A${""}`)).toBe("A");
|
||||
// });
|
||||
@@ -129,3 +141,15 @@ test("namespace import", () => {
|
||||
test("ireturnapromise", async () => {
|
||||
expect(await ireturnapromise()).toEqual("aaa");
|
||||
});
|
||||
|
||||
test("template literals with macros", () => {
|
||||
expect(simpleTag`World`).toBe("Hello World!");
|
||||
expect(interpolateTag`Alice${100}`).toBe("User Alice has 100 points");
|
||||
expect(objectTag`${{ name: "Bob", age: 25 }}`).toBe("Name: Bob, Age: 25");
|
||||
});
|
||||
|
||||
test("template literals with namespace import", () => {
|
||||
expect(macros.simpleTag`Test`).toBe("Hello Test!");
|
||||
expect(macros.interpolateTag`Jane${50}`).toBe("User Jane has 50 points");
|
||||
expect(macros.objectTag`${{ name: "Alice", age: 30 }}`).toBe("Name: Alice, Age: 30");
|
||||
});
|
||||
|
||||
@@ -23,3 +23,16 @@ export async function ireturnapromise() {
|
||||
setTimeout(() => resolve("aaa"), 100);
|
||||
return promise;
|
||||
}
|
||||
|
||||
export function simpleTag(strings: TemplateStringsArray, ..._values: any[]) {
|
||||
return `Hello ${strings[0]}!`;
|
||||
}
|
||||
|
||||
export function interpolateTag(strings: TemplateStringsArray, ...values: any[]) {
|
||||
return `User ${strings[0]} has ${values[0]} points`;
|
||||
}
|
||||
|
||||
export function objectTag(_strings: TemplateStringsArray, ...values: any[]) {
|
||||
const obj = values[0];
|
||||
return `Name: ${obj.name}, Age: ${obj.age}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user