aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-05-05 21:32:19 -0700
committerGravatar Jarred Sumner <jarred@jarredsumner.com> 2022-05-05 21:32:19 -0700
commitd629cfafd6fd148c985b5cd051cc5ec48395dc16 (patch)
tree39a11fb60f61a19802a477a4e690e0f11594c885 /src
parent7b125c9731815452c62fbfb69b241dc9e4eb7c29 (diff)
downloadbun-d629cfafd6fd148c985b5cd051cc5ec48395dc16.tar.gz
bun-d629cfafd6fd148c985b5cd051cc5ec48395dc16.tar.zst
bun-d629cfafd6fd148c985b5cd051cc5ec48395dc16.zip
E.String gets a Rope
Diffstat (limited to 'src')
-rw-r--r--src/bundler.zig9
-rw-r--r--src/bundler/generate_node_modules_bundle.zig4
-rw-r--r--src/bunfig.zig10
-rw-r--r--src/cli/create_command.zig52
-rw-r--r--src/defines.zig4
-rw-r--r--src/env_loader.zig12
-rw-r--r--src/install/install.zig12
-rw-r--r--src/install/npm.zig8
-rw-r--r--src/javascript/jsc/api/transpiler.zig2
-rw-r--r--src/js_ast.zig225
-rw-r--r--src/js_lexer.zig10
-rw-r--r--src/js_parser/js_parser.zig112
-rw-r--r--src/js_printer.zig58
-rw-r--r--src/json_parser.zig25
-rw-r--r--src/resolver/package_json.zig14
-rw-r--r--src/runtime.zig1
-rw-r--r--src/string_immutable.zig1
-rw-r--r--src/toml/toml_lexer.zig2
-rw-r--r--src/toml/toml_parser.zig10
19 files changed, 342 insertions, 229 deletions
diff --git a/src/bundler.zig b/src/bundler.zig
index 13c83434b..3cfc91690 100644
--- a/src/bundler.zig
+++ b/src/bundler.zig
@@ -1077,6 +1077,8 @@ pub const Bundler = struct {
.ts,
.tsx,
=> {
+ const platform = bundler.options.platform;
+
var jsx = this_parse.jsx;
jsx.parse = loader.isJSX();
var opts = js_parser.Parser.Options.init(jsx, loader);
@@ -1084,6 +1086,7 @@ pub const Bundler = struct {
opts.transform_require_to_import = bundler.options.allow_runtime;
opts.features.allow_runtime = bundler.options.allow_runtime;
opts.features.trim_unused_imports = bundler.options.trim_unused_imports orelse loader.isTypeScript();
+ opts.features.should_fold_numeric_constants = platform.isBun();
opts.can_import_from_bundle = bundler.options.node_modules_bundle != null;
@@ -1094,7 +1097,7 @@ pub const Bundler = struct {
// or you're running in SSR
// or the file is a node_module
opts.features.hot_module_reloading = bundler.options.hot_module_reloading and
- bundler.options.platform.isNotBun() and
+ platform.isNotBun() and
(!opts.can_import_from_bundle or
(opts.can_import_from_bundle and !path.isNodeModule()));
opts.features.react_fast_refresh = opts.features.hot_module_reloading and
@@ -1102,7 +1105,7 @@ pub const Bundler = struct {
bundler.options.jsx.supports_fast_refresh;
opts.filepath_hash_for_hmr = file_hash orelse 0;
opts.features.auto_import_jsx = bundler.options.auto_import_jsx;
- opts.warn_about_unbundled_modules = bundler.options.platform.isNotBun();
+ opts.warn_about_unbundled_modules = platform.isNotBun();
if (bundler.macro_context == null) {
bundler.macro_context = js_ast.Macro.MacroContext.init(bundler);
@@ -1114,7 +1117,7 @@ pub const Bundler = struct {
opts.macro_context = &bundler.macro_context.?;
- opts.features.is_macro_runtime = bundler.options.platform == .bun_macro;
+ opts.features.is_macro_runtime = platform == .bun_macro;
opts.features.replace_exports = this_parse.replace_exports;
const value = (bundler.resolver.caches.js.parse(
diff --git a/src/bundler/generate_node_modules_bundle.zig b/src/bundler/generate_node_modules_bundle.zig
index 44cb2618a..21902f9d9 100644
--- a/src/bundler/generate_node_modules_bundle.zig
+++ b/src/bundler/generate_node_modules_bundle.zig
@@ -1443,7 +1443,7 @@ pub fn processFile(this: *GenerateNodeModuleBundle, worker: *ThreadPool.Worker,
const expr = brk: {
// If it's an ascii string, we just print it out with a big old JSON.parse()
if (json_parse_result.tag == .ascii) {
- json_e_string = js_ast.E.String{ .utf8 = source.contents, .prefer_template = true };
+ json_e_string = js_ast.E.String{ .data = source.contents, .prefer_template = true };
var json_string_expr = js_ast.Expr{ .data = .{ .e_string = &json_e_string }, .loc = logger.Loc{ .start = 0 } };
json_call_args[0] = json_string_expr;
json_e_identifier = js_ast.E.Identifier{ .ref = Ref.atIndex(json_ast_symbols_list.len - 1) };
@@ -1514,7 +1514,7 @@ pub fn processFile(this: *GenerateNodeModuleBundle, worker: *ThreadPool.Worker,
}
}
- var package_path = js_ast.E.String{ .utf8 = module_data.package_path };
+ var package_path = js_ast.E.String{ .data = module_data.package_path };
var target_identifier = E.Identifier{ .ref = register_ref };
var cjs_args: [2]js_ast.G.Arg = undefined;
diff --git a/src/bunfig.zig b/src/bunfig.zig
index 2592f91db..950c5c8b0 100644
--- a/src/bunfig.zig
+++ b/src/bunfig.zig
@@ -49,7 +49,7 @@ pub const Bunfig = struct {
switch (expr.data) {
.e_string => |str| {
- const url = URL.parse(str.utf8);
+ const url = URL.parse(str.data);
// Token
if (url.username.len == 0 and url.password.len > 0) {
registry.token = url.password;
@@ -65,22 +65,22 @@ pub const Bunfig = struct {
.e_object => |obj| {
if (obj.get("url")) |url| {
try this.expect(url, .e_string);
- registry.url = url.data.e_string.utf8;
+ registry.url = url.data.e_string.data;
}
if (obj.get("username")) |username| {
try this.expect(username, .e_string);
- registry.username = username.data.e_string.utf8;
+ registry.username = username.data.e_string.data;
}
if (obj.get("password")) |password| {
try this.expect(password, .e_string);
- registry.password = password.data.e_string.utf8;
+ registry.password = password.data.e_string.data;
}
if (obj.get("token")) |token| {
try this.expect(token, .e_string);
- registry.token = token.data.e_string.utf8;
+ registry.token = token.data.e_string.data;
}
},
else => {
diff --git a/src/cli/create_command.zig b/src/cli/create_command.zig
index e5d27fe75..6afcdc3c0 100644
--- a/src/cli/create_command.zig
+++ b/src/cli/create_command.zig
@@ -77,7 +77,7 @@ const UnsupportedPackages = struct {
pub fn update(this: *UnsupportedPackages, expr: js_ast.Expr) void {
for (expr.data.e_object.properties.slice()) |prop| {
inline for (comptime std.meta.fieldNames(UnsupportedPackages)) |field_name| {
- if (strings.eqlComptime(prop.key.?.data.e_string.utf8, comptime field_name)) {
+ if (strings.eqlComptime(prop.key.?.data.e_string.data, comptime field_name)) {
@field(this, field_name) = true;
}
}
@@ -747,7 +747,7 @@ pub const CreateCommand = struct {
if (package_json_expr.asProperty("name")) |name_expr| {
if (name_expr.expr.data == .e_string) {
var basename = std.fs.path.basename(destination);
- name_expr.expr.data.e_string.utf8 = @intToPtr([*]u8, @ptrToInt(basename.ptr))[0..basename.len];
+ name_expr.expr.data.e_string.data = @intToPtr([*]u8, @ptrToInt(basename.ptr))[0..basename.len];
}
}
@@ -786,7 +786,7 @@ pub const CreateCommand = struct {
var i: usize = 0;
var out_i: usize = 0;
while (i < list.len) : (i += 1) {
- const key = list[i].key.?.data.e_string.utf8;
+ const key = list[i].key.?.data.e_string.data;
const do_prune = packages.has(key);
prune_count += @intCast(u16, @boolToInt(do_prune));
@@ -844,7 +844,7 @@ pub const CreateCommand = struct {
is_nextjs = true;
needs.bun_bun_for_nextjs = true;
- next_q.expr.data.e_string.utf8 = constStrToU8(target_nextjs_version);
+ next_q.expr.data.e_string.data = constStrToU8(target_nextjs_version);
}
has_bun_framework_next = has_bun_framework_next or property.hasAnyPropertyNamed(&.{"bun-framework-next"});
@@ -935,17 +935,17 @@ pub const CreateCommand = struct {
const macros_string = "macros";
const bun_macros_relay_path = "bun-macro-relay";
- pub var dependencies_e_string = E.String{ .utf8 = dependencies_string };
- pub var devDependencies_e_string = E.String{ .utf8 = dev_dependencies_string };
- pub var bun_e_string = E.String{ .utf8 = bun_string };
- pub var macros_e_string = E.String{ .utf8 = macros_string };
- pub var react_relay_string = E.String{ .utf8 = "react-relay" };
- pub var bun_macros_relay_path_string = E.String{ .utf8 = "bun-macro-relay" };
- pub var babel_plugin_relay_macro = E.String{ .utf8 = "babel-plugin-relay/macro" };
- pub var babel_plugin_relay_macro_js = E.String{ .utf8 = "babel-plugin-relay/macro.js" };
- pub var graphql_string = E.String{ .utf8 = "graphql" };
+ pub var dependencies_e_string = E.String.init(dependencies_string);
+ pub var devDependencies_e_string = E.String.init(dev_dependencies_string);
+ pub var bun_e_string = E.String.init(bun_string);
+ pub var macros_e_string = E.String.init(macros_string);
+ pub var react_relay_string = E.String.init("react-relay");
+ pub var bun_macros_relay_path_string = E.String.init("bun-macro-relay");
+ pub var babel_plugin_relay_macro = E.String.init("babel-plugin-relay/macro");
+ pub var babel_plugin_relay_macro_js = E.String.init("babel-plugin-relay/macro.js");
+ pub var graphql_string = E.String.init("graphql");
- var npx_react_scripts_build_str = E.String{ .utf8 = "npx react-scripts build" };
+ var npx_react_scripts_build_str = E.String.init("npx react-scripts build");
pub const npx_react_scripts_build = js_ast.Expr{ .data = .{ .e_string = &npx_react_scripts_build_str }, .loc = logger.Loc.Empty };
@@ -1019,7 +1019,7 @@ pub const CreateCommand = struct {
.properties = undefined,
};
- var bun_macros_relay_only_object_string = js_ast.E.String{ .utf8 = "macros" };
+ var bun_macros_relay_only_object_string = js_ast.E.String.init("macros");
pub var bun_macros_relay_only_object_properties = [_]js_ast.G.Property{
js_ast.G.Property{
.key = js_ast.Expr{
@@ -1038,7 +1038,7 @@ pub const CreateCommand = struct {
};
pub var bun_macros_relay_only_object = E.Object{ .properties = undefined };
- var bun_only_macros_string = js_ast.E.String{ .utf8 = "bun" };
+ var bun_only_macros_string = js_ast.E.String.init("bun");
pub var bun_only_macros_relay_property = js_ast.G.Property{
.key = js_ast.Expr{
.data = .{
@@ -1054,8 +1054,8 @@ pub const CreateCommand = struct {
},
};
- pub var bun_framework_next_string = js_ast.E.String{ .utf8 = "bun-framework-next" };
- pub var bun_framework_next_version = js_ast.E.String{ .utf8 = "latest" };
+ pub var bun_framework_next_string = js_ast.E.String.init("bun-framework-next");
+ pub var bun_framework_next_version = js_ast.E.String.init("latest");
pub var bun_framework_next_property = js_ast.G.Property{
.key = js_ast.Expr{
.data = .{
@@ -1071,8 +1071,8 @@ pub const CreateCommand = struct {
},
};
- pub var bun_macro_relay_dependency_string = js_ast.E.String{ .utf8 = "bun-macro-relay" };
- pub var bun_macro_relay_dependency_version = js_ast.E.String{ .utf8 = "latest" };
+ pub var bun_macro_relay_dependency_string = js_ast.E.String.init("bun-macro-relay");
+ pub var bun_macro_relay_dependency_version = js_ast.E.String.init("latest");
pub var bun_macro_relay_dependency = js_ast.G.Property{
.key = js_ast.Expr{
@@ -1089,8 +1089,8 @@ pub const CreateCommand = struct {
},
};
- pub var refresh_runtime_string = js_ast.E.String{ .utf8 = "react-refresh" };
- pub var refresh_runtime_version = js_ast.E.String{ .utf8 = "0.10.0" };
+ pub var refresh_runtime_string = js_ast.E.String.init("react-refresh");
+ pub var refresh_runtime_version = js_ast.E.String.init("0.10.0");
pub var react_refresh_dependency = js_ast.G.Property{
.key = js_ast.Expr{
.data = .{
@@ -1350,7 +1350,7 @@ pub const CreateCommand = struct {
var script_property_out_i: usize = 0;
while (script_property_i < scripts_properties.len) : (script_property_i += 1) {
- const script = scripts_properties[script_property_i].value.?.data.e_string.utf8;
+ const script = scripts_properties[script_property_i].value.?.data.e_string.data;
if (strings.contains(script, "react-scripts start") or
strings.contains(script, "next dev") or
@@ -2079,14 +2079,14 @@ pub const Example = struct {
var list = try ctx.allocator.alloc(Example, count);
for (q.expr.data.e_object.properties.slice()) |property, i| {
- const name = property.key.?.data.e_string.utf8;
+ const name = property.key.?.data.e_string.data;
list[i] = Example{
.name = if (std.mem.indexOfScalar(u8, name, '/')) |slash|
name[slash + 1 ..]
else
name,
- .version = property.value.?.asProperty("version").?.expr.data.e_string.utf8,
- .description = property.value.?.asProperty("description").?.expr.data.e_string.utf8,
+ .version = property.value.?.asProperty("version").?.expr.data.e_string.data,
+ .description = property.value.?.asProperty("description").?.expr.data.e_string.data,
};
}
return list;
diff --git a/src/defines.zig b/src/defines.zig
index c50235158..507ad8851 100644
--- a/src/defines.zig
+++ b/src/defines.zig
@@ -198,8 +198,8 @@ var inf_val = js_ast.E.Number{ .value = std.math.inf_f64 };
const __dirname_str: string = std.fs.path.sep_str ++ "__dirname_is_not_implemented";
const __filename_str: string = "__filename_is_not_implemented.js";
-var __dirname = js_ast.E.String{ .utf8 = __dirname_str };
-var __filename = js_ast.E.String{ .utf8 = __filename_str };
+var __dirname = js_ast.E.String.init(__dirname_str);
+var __filename = js_ast.E.String.init(__filename_str);
pub const Define = struct {
identifiers: std.StringHashMap(IdentifierDefine),
diff --git a/src/env_loader.zig b/src/env_loader.zig
index 388760513..55e1d74f0 100644
--- a/src/env_loader.zig
+++ b/src/env_loader.zig
@@ -517,7 +517,7 @@ pub const Loader = struct {
const key_str = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable;
e_strings[0] = js_ast.E.String{
- .utf8 = if (value.len > 0)
+ .data = if (value.len > 0)
@intToPtr([*]u8, @ptrToInt(value.ptr))[0..value.len]
else
&[_]u8{},
@@ -564,7 +564,7 @@ pub const Loader = struct {
if (std.mem.indexOfScalar(u64, string_map_hashes, hash)) |key_i| {
e_strings[0] = js_ast.E.String{
- .utf8 = if (value.len > 0)
+ .data = if (value.len > 0)
@intToPtr([*]u8, @ptrToInt(value.ptr))[0..value.len]
else
&[_]u8{},
@@ -614,7 +614,7 @@ pub const Loader = struct {
const key = std.fmt.allocPrint(key_allocator, "process.env.{s}", .{entry.key_ptr.*}) catch unreachable;
e_strings[0] = js_ast.E.String{
- .utf8 = if (entry.value_ptr.*.len > 0)
+ .data = if (entry.value_ptr.*.len > 0)
@intToPtr([*]u8, @ptrToInt(entry.value_ptr.*.ptr))[0..value.len]
else
&[_]u8{},
@@ -1167,8 +1167,8 @@ test "DotEnv Loader - copyForDefine" {
);
try expect(env_defines.get("process.env.BACON") != null);
- try expectString(env_defines.get("process.env.BACON").?.value.e_string.utf8, "false");
- try expectString(env_defines.get("process.env.HOSTNAME").?.value.e_string.utf8, "example.com");
+ try expectString(env_defines.get("process.env.BACON").?.value.e_string.data, "false");
+ try expectString(env_defines.get("process.env.HOSTNAME").?.value.e_string.data, "example.com");
try expect(env_defines.get("process.env.THIS_SHOULDNT_BE_IN_DEFINES_MAP") != null);
user_defines = UserDefine.init(default_allocator);
@@ -1176,6 +1176,6 @@ test "DotEnv Loader - copyForDefine" {
buf = try loader.copyForDefine(UserDefine, &user_defines, UserDefinesArray, &env_defines, framework, .prefix, "HO", default_allocator);
- try expectString(env_defines.get("process.env.HOSTNAME").?.value.e_string.utf8, "example.com");
+ try expectString(env_defines.get("process.env.HOSTNAME").?.value.e_string.data, "example.com");
try expect(env_defines.get("process.env.THIS_SHOULDNT_BE_IN_DEFINES_MAP") == null);
}
diff --git a/src/install/install.zig b/src/install/install.zig
index 0e033b960..b16b39813 100644
--- a/src/install/install.zig
+++ b/src/install/install.zig
@@ -3041,7 +3041,7 @@ pub const PackageManager = struct {
new_dependencies[k].key = JSAst.Expr.init(
JSAst.E.String,
JSAst.E.String{
- .utf8 = update.name,
+ .data = update.name,
},
logger.Loc.Empty,
);
@@ -3050,7 +3050,7 @@ pub const PackageManager = struct {
JSAst.E.String,
JSAst.E.String{
// we set it later
- .utf8 = "",
+ .data = "",
},
logger.Loc.Empty,
);
@@ -3098,7 +3098,7 @@ pub const PackageManager = struct {
.key = JSAst.Expr.init(
JSAst.E.String,
JSAst.E.String{
- .utf8 = dependency_list,
+ .data = dependency_list,
},
logger.Loc.Empty,
),
@@ -3111,7 +3111,7 @@ pub const PackageManager = struct {
root_properties[root_properties.len - 1].key = JSAst.Expr.init(
JSAst.E.String,
JSAst.E.String{
- .utf8 = dependency_list,
+ .data = dependency_list,
},
logger.Loc.Empty,
);
@@ -3127,9 +3127,9 @@ pub const PackageManager = struct {
var str = update.e_string.?;
if (update.version.tag == .uninitialized) {
- str.utf8 = latest;
+ str.data = latest;
} else {
- str.utf8 = update.version.literal.slice(update.version_buf);
+ str.data = update.version.literal.slice(update.version_buf);
}
}
}
diff --git a/src/install/npm.zig b/src/install/npm.zig
index ac12cc942..796a88c7b 100644
--- a/src/install/npm.zig
+++ b/src/install/npm.zig
@@ -1031,7 +1031,7 @@ pub const PackageManifest = struct {
}
},
.e_string => |str| {
- package_version.cpu = Architecture.apply(Architecture.none, str.utf8);
+ package_version.cpu = Architecture.apply(Architecture.none, str.data);
},
else => {},
}
@@ -1053,7 +1053,7 @@ pub const PackageManifest = struct {
}
},
.e_string => |str| {
- package_version.os = OperatingSystem.apply(OperatingSystem.none, str.utf8);
+ package_version.os = OperatingSystem.apply(OperatingSystem.none, str.data);
},
else => {},
}
@@ -1118,11 +1118,11 @@ pub const PackageManifest = struct {
break :bin;
},
.e_string => |str| {
- if (str.utf8.len > 0) {
+ if (str.data.len > 0) {
package_version.bin = Bin{
.tag = Bin.Tag.file,
.value = .{
- .file = string_builder.append(String, str.utf8),
+ .file = string_builder.append(String, str.data),
},
};
break :bin;
diff --git a/src/javascript/jsc/api/transpiler.zig b/src/javascript/jsc/api/transpiler.zig
index 9b4fce4de..404475460 100644
--- a/src/javascript/jsc/api/transpiler.zig
+++ b/src/javascript/jsc/api/transpiler.zig
@@ -317,7 +317,7 @@ fn exportReplacementValue(value: JSValue, globalThis: *JSGlobalObject) ?JSAst.Ex
if (value.isString()) {
var str = JSAst.E.String{
- .utf8 = std.fmt.allocPrint(bun.default_allocator, "{}", .{value.getZigString(globalThis)}) catch unreachable,
+ .data = std.fmt.allocPrint(bun.default_allocator, "{}", .{value.getZigString(globalThis)}) catch unreachable,
};
var out = bun.default_allocator.create(JSAst.E.String) catch unreachable;
out.* = str;
diff --git a/src/js_ast.zig b/src/js_ast.zig
index 80f754a2c..96b14c363 100644
--- a/src/js_ast.zig
+++ b/src/js_ast.zig
@@ -1328,6 +1328,11 @@ pub const E = struct {
return @floatToInt(u64, @maximum(@trunc(self.value), 0));
}
+ pub inline fn toUsize(self: Number) usize {
+ @setRuntimeSafety(false);
+ return @floatToInt(usize, @maximum(@trunc(self.value), 0));
+ }
+
pub inline fn toU32(self: Number) u32 {
@setRuntimeSafety(false);
return @floatToInt(u32, @maximum(@trunc(self.value), 0));
@@ -1421,7 +1426,7 @@ pub const E = struct {
pub const SetError = error{ OutOfMemory, Clobber };
pub fn set(self: *const Object, key: Expr, allocator: std.mem.Allocator, value: Expr) SetError!void {
- if (self.hasProperty(key.data.e_string.utf8)) return error.Clobber;
+ if (self.hasProperty(key.data.e_string.data)) return error.Clobber;
try self.properties.push(allocator, .{
.key = key,
.value = value,
@@ -1435,7 +1440,7 @@ pub const E = struct {
// this is terribly, shamefully slow
pub fn setRope(self: *Object, rope: *const Rope, allocator: std.mem.Allocator, value: Expr) SetError!void {
- if (self.get(rope.head.data.e_string.utf8)) |existing| {
+ if (self.get(rope.head.data.e_string.data)) |existing| {
switch (existing.data) {
.e_array => |array| {
if (rope.next == null) {
@@ -1483,7 +1488,7 @@ pub const E = struct {
}
pub fn getOrPutObject(self: *Object, rope: *const Rope, allocator: std.mem.Allocator) SetError!Expr {
- if (self.get(rope.head.data.e_string.utf8)) |existing| {
+ if (self.get(rope.head.data.e_string.data)) |existing| {
switch (existing.data) {
.e_array => |array| {
if (rope.next == null) {
@@ -1533,7 +1538,7 @@ pub const E = struct {
}
pub fn getOrPutArray(self: *Object, rope: *const Rope, allocator: std.mem.Allocator) SetError!Expr {
- if (self.get(rope.head.data.e_string.utf8)) |existing| {
+ if (self.get(rope.head.data.e_string.data)) |existing| {
switch (existing.data) {
.e_array => |array| {
if (rope.next == null) {
@@ -1653,17 +1658,17 @@ pub const E = struct {
var rhs_key_size: u8 = @enumToInt(Fields.__fake);
if (lhs.key != null and lhs.key.?.data == .e_string) {
- lhs_key_size = @enumToInt(Map.get(lhs.key.?.data.e_string.utf8) orelse Fields.__fake);
+ lhs_key_size = @enumToInt(Map.get(lhs.key.?.data.e_string.data) orelse Fields.__fake);
}
if (rhs.key != null and rhs.key.?.data == .e_string) {
- rhs_key_size = @enumToInt(Map.get(rhs.key.?.data.e_string.utf8) orelse Fields.__fake);
+ rhs_key_size = @enumToInt(Map.get(rhs.key.?.data.e_string.data) orelse Fields.__fake);
}
return switch (std.math.order(lhs_key_size, rhs_key_size)) {
.lt => true,
.gt => false,
- .eq => strings.cmpStringsAsc(ctx, lhs.key.?.data.e_string.utf8, rhs.key.?.data.e_string.utf8),
+ .eq => strings.cmpStringsAsc(ctx, lhs.key.?.data.e_string.data, rhs.key.?.data.e_string.data),
};
}
};
@@ -1671,7 +1676,7 @@ pub const E = struct {
const Sorter = struct {
pub fn isLessThan(ctx: void, lhs: G.Property, rhs: G.Property) bool {
- return strings.cmpStringsAsc(ctx, lhs.key.?.data.e_string.utf8, rhs.key.?.data.e_string.utf8);
+ return strings.cmpStringsAsc(ctx, lhs.key.?.data.e_string.data, rhs.key.?.data.e_string.data);
}
};
};
@@ -1682,36 +1687,110 @@ pub const E = struct {
pub const String = struct {
// A version of this where `utf8` and `value` are stored in a packed union, with len as a single u32 was attempted.
// It did not improve benchmarks. Neither did converting this from a heap-allocated type to a stack-allocated type.
- value: []const u16 = &.{},
- utf8: bun.string = &([_]u8{}),
+ data: []const u8 = "",
prefer_template: bool = false,
- pub var empty = String{};
- pub var @"true" = String{ .utf8 = "true" };
- pub var @"false" = String{ .utf8 = "false" };
- pub var @"null" = String{ .utf8 = "null" };
- pub var @"undefined" = String{ .utf8 = "undefined" };
+ // A very simple rope implementation
+ // We only use this for string folding, so this is kind of overkill
+ // We don't need to deal with substrings
+ next: ?*String = null,
+ end: ?*String = null,
+ rope_len: u32 = 0,
+ is_utf16: bool = false,
- pub fn clone(str: *const String, allocator: std.mem.Allocator) !String {
- if (str.isUTF8()) {
- return String{
- .utf8 = try allocator.dupe(u8, str.utf8),
- .prefer_template = str.prefer_template,
- };
+ pub fn push(this: *String, other: *String) void {
+ std.debug.assert(this.isUTF8());
+ std.debug.assert(other.isUTF8());
+
+ if (other.rope_len == 0) {
+ other.rope_len = @truncate(u32, other.data.len);
+ }
+
+ if (this.rope_len == 0) {
+ this.rope_len = @truncate(u32, this.data.len);
+ }
+
+ this.rope_len += other.rope_len;
+ if (this.next == null) {
+ this.next = other;
+ this.end = other;
} else {
- return String{
- .value = try allocator.dupe(u16, str.value),
- .prefer_template = str.prefer_template,
+ this.end.?.next = other;
+ this.end = other;
+ }
+ }
+
+ pub fn toUTF8(this: *String, allocator: std.mem.Allocator) !void {
+ if (!this.is_utf16) return;
+ this.data = try strings.toUTF8Alloc(allocator, this.slice16());
+ this.is_utf16 = false;
+ }
+
+ pub fn init(value: anytype) String {
+ const Value = @TypeOf(value);
+ if (Value == []u16 or Value == []const u16) {
+ return .{
+ .data = @ptrCast([*]const u8, value.ptr)[0..value.len],
+ .is_utf16 = true,
};
}
+ return .{
+ .data = value,
+ };
+ }
+
+ pub fn slice16(this: *const String) []const u16 {
+ std.debug.assert(this.is_utf16);
+ return @ptrCast([*]const u16, @alignCast(@alignOf(u16), this.data.ptr))[0..this.data.len];
+ }
+
+ pub fn resovleRopeIfNeeded(this: *String, allocator: std.mem.Allocator) void {
+ if (this.next == null or !this.isUTF8()) return;
+ var bytes = allocator.alloc(u8, this.rope_len) catch unreachable;
+ var ptr = bytes.ptr;
+ var remain = bytes.len;
+ @memcpy(ptr, this.data.ptr, this.data.len);
+ ptr += this.data.len;
+ remain -= this.data.len;
+ var str = this.next;
+ while (str) |strin| {
+ @memcpy(ptr, strin.data.ptr, strin.data.len);
+ ptr += strin.data.len;
+ remain -= strin.data.len;
+ var prev = strin;
+ str = strin.next;
+ prev.next = null;
+ prev.end = null;
+ }
+ this.data = bytes;
+ this.next = null;
+ }
+
+ pub fn slice(this: *String, allocator: std.mem.Allocator) []const u8 {
+ this.resovleRopeIfNeeded(allocator);
+ return @ptrCast([*]const u8, @alignCast(@alignOf(u8), this.data.ptr))[0..this.data.len];
+ }
+
+ pub var empty = String{};
+ pub var @"true" = String{ .data = "true" };
+ pub var @"false" = String{ .data = "false" };
+ pub var @"null" = String{ .data = "null" };
+ pub var @"undefined" = String{ .data = "undefined" };
+
+ pub fn clone(str: *const String, allocator: std.mem.Allocator) !String {
+ return String{
+ .data = try allocator.dupe(u8, str.data),
+ .prefer_template = str.prefer_template,
+ .is_utf16 = !str.isUTF8(),
+ };
}
pub inline fn len(s: *const String) usize {
- return @maximum(s.utf8.len, s.value.len);
+ return if (s.rope_len > 0) s.rope_len else s.data.len;
}
pub inline fn isUTF8(s: *const String) bool {
- return s.len() == s.utf8.len;
+ return !s.is_utf16;
}
pub inline fn isBlank(s: *const String) bool {
@@ -1727,16 +1806,16 @@ pub const E = struct {
switch (_t) {
@This() => {
if (other.isUTF8()) {
- return strings.eql(s.utf8, other.utf8);
+ return strings.eql(s.data, other.data);
} else {
- return strings.utf16EqlString(other.value, s.utf8);
+ return strings.utf16EqlString(other.slice16(), s.data);
}
},
bun.string => {
- return strings.eql(s.utf8, other);
+ return strings.eql(s.data, other);
},
[]u16, []const u16 => {
- return strings.utf16EqlString(other, s.utf8);
+ return strings.utf16EqlString(other, s.data);
},
else => {
@compileError("Invalid type");
@@ -1746,16 +1825,16 @@ pub const E = struct {
switch (_t) {
@This() => {
if (other.isUTF8()) {
- return strings.utf16EqlString(s.value, other.utf8);
+ return strings.utf16EqlString(s.slice16(), other.data);
} else {
- return std.mem.eql(u16, other.value, s.value);
+ return std.mem.eql(u16, other.slice16(), s.slice16());
}
},
bun.string => {
- return strings.utf16EqlString(s.value, other);
+ return strings.utf16EqlString(s.slice16(), other);
},
[]u16, []const u16 => {
- return std.mem.eql(u16, other.value, s.value);
+ return std.mem.eql(u16, other.slice16(), s.slice16());
},
else => {
@compileError("Invalid type");
@@ -1766,16 +1845,16 @@ pub const E = struct {
pub fn eqlComptime(s: *const String, comptime value: anytype) bool {
return if (s.isUTF8())
- strings.eqlComptime(s.utf8, value)
+ strings.eqlComptime(s.data, value)
else
- strings.eqlComptimeUTF16(s.value, value);
+ strings.eqlComptimeUTF16(s.slice16(), value);
}
pub fn string(s: *const String, allocator: std.mem.Allocator) !bun.string {
if (s.isUTF8()) {
- return s.utf8;
+ return s.data;
} else {
- return strings.toUTF8Alloc(allocator, s.value);
+ return strings.toUTF8Alloc(allocator, s.slice16());
}
}
@@ -1784,17 +1863,17 @@ pub const E = struct {
if (s.isUTF8()) {
// hash utf-8
- return std.hash.Wyhash.hash(0, s.utf8);
+ return std.hash.Wyhash.hash(0, s.data);
} else {
// hash utf-16
- return std.hash.Wyhash.hash(0, @ptrCast([*]const u8, s.value.ptr)[0 .. s.value.len * 2]);
+ return std.hash.Wyhash.hash(0, @ptrCast([*]const u8, s.slice16().ptr)[0 .. s.slice16().len * 2]);
}
}
pub fn jsonStringify(s: *const String, options: anytype, writer: anytype) !void {
var buf = [_]u8{0} ** 4096;
var i: usize = 0;
- for (s.value) |char| {
+ for (s.slice16()) |char| {
buf[i] = @intCast(u8, char);
i += 1;
if (i >= 4096) {
@@ -2233,13 +2312,13 @@ pub const Expr = struct {
if (list.len > 0) {
list = list[1 .. list.len - 1];
}
- return Expr.init(E.String, E.String{ .utf8 = list }, loc);
+ return Expr.init(E.String, E.String.init(list), loc);
}
return Expr.init(
E.String,
E.String{
- .utf8 = try JSC.ZigString.init(bytes).toBase64DataURL(allocator),
+ .data = try JSC.ZigString.init(bytes).toBase64DataURL(allocator),
},
loc,
);
@@ -2272,7 +2351,7 @@ pub const Expr = struct {
const key = prop.key orelse continue;
if (std.meta.activeTag(key.data) != .e_string) continue;
const key_str = key.data.e_string;
- if (strings.eqlAnyComptime(key_str.utf8, names)) return true;
+ if (strings.eqlAnyComptime(key_str.data, names)) return true;
}
return false;
@@ -2287,7 +2366,7 @@ pub const Expr = struct {
}
pub fn getRope(self: *const Expr, rope: *const E.Object.Rope) ?E.Object.RopeQuery {
- if (self.get(rope.head.data.e_string.utf8)) |existing| {
+ if (self.get(rope.head.data.e_string.data)) |existing| {
switch (existing.data) {
.e_array => |array| {
if (rope.next) |next| {
@@ -2358,7 +2437,7 @@ pub const Expr = struct {
const key_str = expr.data.e_string;
- return if (key_str.isUTF8()) key_str.utf8 else key_str.string(allocator) catch null;
+ return if (key_str.isUTF8()) key_str.data else key_str.string(allocator) catch null;
}
pub fn asBool(
@@ -2750,11 +2829,9 @@ pub const Expr = struct {
E.String => {
if (comptime Environment.isDebug) {
// Sanity check: assert string is not a null ptr
- if (st.isUTF8() and st.utf8.len > 0) {
- std.debug.assert(@ptrToInt(st.utf8.ptr) > 0);
- std.debug.assert(st.utf8[0] > 0);
- } else if (st.value.len > 0) {
- std.debug.assert(@ptrToInt(st.value.ptr) > 0);
+ if (st.data.len > 0 and st.isUTF8()) {
+ std.debug.assert(@ptrToInt(st.data.ptr) > 0);
+ std.debug.assert(st.data[0] > 0);
}
}
return Expr{
@@ -5051,9 +5128,9 @@ pub const Macro = struct {
}
if (str.isUTF8()) {
- return JSC.ZigString.init(str.utf8).toValue(ctx.ptr()).asRef();
+ return JSC.ZigString.init(str.data).toValue(ctx.ptr()).asRef();
} else {
- return js.JSValueMakeString(ctx, js.JSStringCreateWithCharactersNoCopy(str.value.ptr, str.value.len));
+ return js.JSValueMakeString(ctx, js.JSStringCreateWithCharactersNoCopy(str.slice16().ptr, str.slice16().len));
}
}
@@ -5198,9 +5275,9 @@ pub const Macro = struct {
}
if (str.isUTF8()) {
- return JSC.ZigString.init(str.utf8).toValue(ctx.ptr()).asRef();
+ return JSC.ZigString.init(str.data).toValue(ctx.ptr()).asRef();
} else {
- return js.JSValueMakeString(ctx, js.JSStringCreateWithCharactersNoCopy(str.value.ptr, str.value.len));
+ return js.JSValueMakeString(ctx, js.JSStringCreateWithCharactersNoCopy(str.slice16().ptr, str.slice16().len));
}
},
// .e_number => |number| {
@@ -5946,7 +6023,7 @@ pub const Macro = struct {
for (props) |prop, i| {
const key = prop.key orelse continue;
if (key.data != .e_string or !key.data.e_string.isUTF8()) continue;
- if (strings.eqlComptime(key.data.e_string.utf8, name)) return @intCast(u32, i);
+ if (strings.eqlComptime(key.data.e_string.data, name)) return @intCast(u32, i);
}
return null;
@@ -5956,7 +6033,7 @@ pub const Macro = struct {
for (props) |prop| {
const key = prop.key orelse continue;
if (key.data != .e_string or !key.data.e_string.isUTF8()) continue;
- if (strings.eqlComptime(key.data.e_string.utf8, name)) return prop.value;
+ if (strings.eqlComptime(key.data.e_string.data, name)) return prop.value;
}
return null;
@@ -6086,7 +6163,7 @@ pub const Macro = struct {
return self.writeElement(el.*);
},
.e_string => |str| {
- self.args.appendAssumeCapacity(Expr.init(E.BigInt, E.BigInt{ .value = std.mem.trimRight(u8, str.utf8, "n") }, value.loc));
+ self.args.appendAssumeCapacity(Expr.init(E.BigInt, E.BigInt{ .value = std.mem.trimRight(u8, str.data, "n") }, value.loc));
},
.e_big_int => {
self.args.appendAssumeCapacity(value);
@@ -6316,7 +6393,7 @@ pub const Macro = struct {
switch (value.data) {
.e_string => |str| {
- self.args.appendAssumeCapacity(Expr.init(E.RegExp, E.RegExp{ .value = str.utf8 }, value.loc));
+ self.args.appendAssumeCapacity(Expr.init(E.RegExp, E.RegExp{ .value = str.data }, value.loc));
},
.e_reg_exp => {
self.args.appendAssumeCapacity(value);
@@ -6687,17 +6764,17 @@ pub const Macro = struct {
const str = tag_expr.data.e_string;
var p = self.p;
- const node_type: JSNode.Tag = JSNode.Tag.names.get(str.utf8) orelse {
+ const node_type: JSNode.Tag = JSNode.Tag.names.get(str.data) orelse {
if (!str.isUTF8()) {
- self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{strings.toUTF8Alloc(self.p.allocator, str.value)}) catch unreachable;
+ self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{strings.toUTF8Alloc(self.p.allocator, str.slice16())}) catch unreachable;
} else {
- self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{str.utf8}) catch unreachable;
+ self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{str.data}) catch unreachable;
}
return false;
};
if (!valid_tags.get(node_type)) {
- self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid here", .{str.utf8}) catch unreachable;
+ self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid here", .{str.data}) catch unreachable;
}
return self.writeNodeType(node_type, element.properties.slice(), element.children.slice(), tag_expr.loc);
@@ -6709,11 +6786,11 @@ pub const Macro = struct {
const str = tag_expr.data.e_string;
var p = self.p;
- const node_type: JSNode.Tag = JSNode.Tag.names.get(str.utf8) orelse {
+ const node_type: JSNode.Tag = JSNode.Tag.names.get(str.data) orelse {
if (!str.isUTF8()) {
- self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{strings.toUTF8Alloc(self.p.allocator, str.value)}) catch unreachable;
+ self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{strings.toUTF8Alloc(self.p.allocator, str.slice16())}) catch unreachable;
} else {
- self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{str.utf8}) catch unreachable;
+ self.log.addErrorFmt(p.source, tag_expr.loc, p.allocator, "Tag \"{s}\" is invalid", .{str.data}) catch unreachable;
}
return false;
};
@@ -7142,9 +7219,9 @@ pub const Macro = struct {
},
};
} else if (wtf_string.is8Bit()) {
- expr.* = Expr.init(E.String, E.String{ .utf8 = wtf_string.characters8()[0..wtf_string.length()] }, writer.loc);
+ expr.* = Expr.init(E.String, E.String.init(wtf_string.characters8()[0..wtf_string.length()]), writer.loc);
} else if (wtf_string.is16Bit()) {
- expr.* = Expr.init(E.String, E.String{ .value = wtf_string.characters16()[0..wtf_string.length()] }, writer.loc);
+ expr.* = Expr.init(E.String, E.String.init(wtf_string.characters16()[0..wtf_string.length()]), writer.loc);
} else {
unreachable;
}
@@ -7481,7 +7558,7 @@ pub const Macro = struct {
for (properties) |property| {
const key = property.key orelse continue;
if (key.data != .e_string) continue;
- const str = key.data.e_string.utf8;
+ const str = key.data.e_string.data;
if (strings.eql(property_slice, str)) {
const value = property.value orelse return js.JSValueMakeUndefined(ctx);
@@ -7508,7 +7585,7 @@ pub const Macro = struct {
for (properties) |property| {
const key = property.key orelse continue;
if (key.data != .e_string) continue;
- const str = key.data.e_string.utf8;
+ const str = key.data.e_string.data;
if (strings.eql(property_slice, str)) return true;
}
@@ -7528,7 +7605,7 @@ pub const Macro = struct {
for (properties) |property| {
const key = property.key orelse continue;
if (key.data != .e_string) continue;
- const str = key.data.e_string.utf8;
+ const str = key.data.e_string.data;
js.JSPropertyNameAccumulatorAddName(props, js.JSStringCreateStatic(str.ptr, str.len));
}
}
@@ -7926,10 +8003,10 @@ pub const Macro = struct {
var property_name_ref = JSC.C.JSPropertyNameArrayGetNameAtIndex(array, i);
defer JSC.C.JSStringRelease(property_name_ref);
properties[i] = G.Property{
- .key = Expr.init(E.String, E.String{ .utf8 = this.allocator.dupe(
+ .key = Expr.init(E.String, E.String.init(this.allocator.dupe(
u8,
JSC.C.JSStringGetCharacters8Ptr(property_name_ref)[0..JSC.C.JSStringGetLength(property_name_ref)],
- ) catch unreachable }, this.caller.loc),
+ ) catch unreachable), this.caller.loc),
.value = try this.run(
JSC.JSValue.fromRef(JSC.C.JSObjectGetProperty(this.global.ref(), object, property_name_ref, null)),
),
@@ -7966,7 +8043,7 @@ pub const Macro = struct {
var zig_str = value.getZigString(this.global);
zig_str.detectEncoding();
var sliced = zig_str.toSlice(this.allocator);
- return Expr.init(E.String, E.String{ .utf8 = sliced.slice() }, this.caller.loc);
+ return Expr.init(E.String, E.String.init(sliced.slice()), this.caller.loc);
},
.Promise => {
var _entry = this.visited.getOrPut(this.allocator, value) catch unreachable;
diff --git a/src/js_lexer.zig b/src/js_lexer.zig
index 6e8563c70..d771b919a 100644
--- a/src/js_lexer.zig
+++ b/src/js_lexer.zig
@@ -1853,17 +1853,19 @@ fn NewLexer_(
pub fn toEString(lexer: *LexerType) js_ast.E.String {
if (lexer.string_literal_is_ascii) {
- return js_ast.E.String{ .utf8 = lexer.string_literal_slice };
+ return js_ast.E.String.init(lexer.string_literal_slice);
} else {
- return js_ast.E.String{ .value = lexer.allocator.dupe(u16, lexer.string_literal) catch unreachable };
+ return js_ast.E.String.init(lexer.allocator.dupe(u16, lexer.string_literal) catch unreachable);
}
}
pub fn toUTF8EString(lexer: *LexerType) js_ast.E.String {
if (lexer.string_literal_is_ascii) {
- return js_ast.E.String{ .utf8 = lexer.string_literal_slice };
+ return js_ast.E.String.init(lexer.string_literal_slice);
} else {
- return js_ast.E.String{ .utf8 = lexer.utf16ToString(lexer.string_literal) };
+ var e_str = js_ast.E.String.init(lexer.string_literal);
+ e_str.toUTF8(lexer.allocator) catch unreachable;
+ return e_str;
}
}
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig
index f36d51981..291466dd0 100644
--- a/src/js_parser/js_parser.zig
+++ b/src/js_parser/js_parser.zig
@@ -103,6 +103,29 @@ pub const AllocatedNamesPool = ObjectPool(
4,
);
+fn foldStringAddition(lhs: Expr, rhs: Expr) ?Expr {
+ switch (lhs.data) {
+ .e_string => |left| {
+ if (rhs.data == .e_string and left.isUTF8() and rhs.data.e_string.isUTF8()) {
+ lhs.data.e_string.push(rhs.data.e_string);
+ return lhs;
+ }
+ },
+ .e_binary => |bin| {
+
+ // 123 + "bar" + "baz"
+ if (bin.op == .bin_add) {
+ if (foldStringAddition(bin.right, rhs)) |out| {
+ return Expr.init(E.Binary, E.Binary{ .op = bin.op, .left = bin.left, .right = out }, lhs.loc);
+ }
+ }
+ },
+ else => {},
+ }
+
+ return null;
+}
+
// If we are currently in a hoisted child of the module scope, relocate these
// declarations to the top level and return an equivalent assignment statement.
// Make sure to check that the declaration kind is "var" before calling this.
@@ -222,7 +245,7 @@ const JSXTag = struct {
if (strings.containsComptime(name, "-:") or (p.lexer.token != .t_dot and name[0] >= 'a' and name[0] <= 'z')) {
return JSXTag{
.data = Data{ .tag = p.e(E.String{
- .utf8 = name,
+ .data = name,
}, loc) },
.range = tag_range,
};
@@ -2287,6 +2310,7 @@ pub const Parser = struct {
fn _parse(self: *Parser, comptime ParserType: type) !js_ast.Result {
var p: ParserType = undefined;
try ParserType.init(self.allocator, self.log, self.source, self.define, self.lexer, self.options, &p);
+ p.should_fold_numeric_constants = self.options.features.should_fold_numeric_constants;
defer p.lexer.deinit();
var result: js_ast.Result = undefined;
@@ -2577,7 +2601,7 @@ pub const Parser = struct {
},
loc,
),
- .value = p.e(E.String{ .utf8 = p.source.path.pretty }, loc),
+ .value = p.e(E.String{ .data = p.source.path.pretty }, loc),
};
decl_i += 1;
}
@@ -3032,7 +3056,7 @@ pub const Prefill = struct {
Expr{ .data = .{ .e_boolean = E.Boolean{ .value = false } }, .loc = logger.Loc.Empty },
};
pub var ActivateString = E.String{
- .utf8 = "activate",
+ .data = "activate",
};
pub var ActivateIndex = E.Index{
.index = .{
@@ -3056,11 +3080,11 @@ pub const Prefill = struct {
pub const Zero = E.Number{ .value = 0.0 };
};
pub const String = struct {
- pub var Key = E.String{ .utf8 = &Prefill.StringLiteral.Key };
- pub var Children = E.String{ .utf8 = &Prefill.StringLiteral.Children };
- pub var Filename = E.String{ .utf8 = &Prefill.StringLiteral.Filename };
- pub var LineNumber = E.String{ .utf8 = &Prefill.StringLiteral.LineNumber };
- pub var ColumnNumber = E.String{ .utf8 = &Prefill.StringLiteral.ColumnNumber };
+ pub var Key = E.String{ .data = &Prefill.StringLiteral.Key };
+ pub var Children = E.String{ .data = &Prefill.StringLiteral.Children };
+ pub var Filename = E.String{ .data = &Prefill.StringLiteral.Filename };
+ pub var LineNumber = E.String{ .data = &Prefill.StringLiteral.LineNumber };
+ pub var ColumnNumber = E.String{ .data = &Prefill.StringLiteral.ColumnNumber };
};
pub const Data = struct {
pub var BMissing = B{ .b_missing = BMissing_ };
@@ -7883,7 +7907,7 @@ fn NewParser_(
try p.lexer.next();
- key = p.e(E.String{ .utf8 = name }, loc);
+ key = p.e(E.String{ .data = name }, loc);
if (p.lexer.token != .t_colon and p.lexer.token != .t_open_paren) {
const ref = p.storeNameInRef(name) catch unreachable;
@@ -7997,7 +8021,7 @@ fn NewParser_(
if (p.lexer.token == .t_string_literal) {
value.name = p.lexer.toEString();
} else if (p.lexer.isIdentifierOrKeyword()) {
- value.name = E.String{ .utf8 = p.lexer.identifier };
+ value.name = E.String{ .data = p.lexer.identifier };
needs_symbol = true;
} else {
try p.lexer.expect(.t_identifier);
@@ -9276,7 +9300,7 @@ fn NewParser_(
}
}
- key = p.e(E.String{ .utf8 = name }, name_range.loc);
+ key = p.e(E.String{ .data = name }, name_range.loc);
// Parse a shorthand property
const isShorthandProperty = !opts.is_class and
@@ -11307,7 +11331,7 @@ fn NewParser_(
if (comptime only_scan_imports_and_do_not_visit) {
if (value.data == .e_string and value.data.e_string.isUTF8() and value.data.e_string.isPresent()) {
- const import_record_index = p.addImportRecord(.dynamic, value.loc, value.data.e_string.utf8);
+ const import_record_index = p.addImportRecord(.dynamic, value.loc, value.data.e_string.slice(p.allocator));
return p.e(E.Import{
.expr = value,
@@ -11390,7 +11414,7 @@ fn NewParser_(
continue;
}
- const prop_name = p.e(E.String{ .utf8 = prop_name_literal }, key_range.loc);
+ const prop_name = p.e(E.String{ .data = prop_name_literal }, key_range.loc);
// Parse the value
var value: Expr = undefined;
@@ -11430,13 +11454,13 @@ fn NewParser_(
const key = brk: {
switch (expr.data) {
.e_import_identifier => |ident| {
- break :brk p.e(E.String{ .utf8 = p.loadNameFromRef(ident.ref) }, expr.loc);
+ break :brk p.e(E.String{ .data = p.loadNameFromRef(ident.ref) }, expr.loc);
},
.e_identifier => |ident| {
- break :brk p.e(E.String{ .utf8 = p.loadNameFromRef(ident.ref) }, expr.loc);
+ break :brk p.e(E.String{ .data = p.loadNameFromRef(ident.ref) }, expr.loc);
},
.e_dot => |dot| {
- break :brk p.e(E.String{ .utf8 = dot.name }, dot.name_loc);
+ break :brk p.e(E.String{ .data = dot.name }, dot.name_loc);
},
.e_index => |index| {
if (index.index.data == .e_string) {
@@ -12088,14 +12112,14 @@ fn NewParser_(
const runtime = if (p.options.jsx.runtime == .automatic and !e_.flags.is_key_before_rest) options.JSX.Runtime.automatic else options.JSX.Runtime.classic;
var children_count = e_.children.len;
- const is_childless_tag = FeatureFlags.react_specific_warnings and children_count > 0 and tag.data == .e_string and tag.data.e_string.isUTF8() and js_lexer.ChildlessJSXTags.has(tag.data.e_string.utf8);
+ const is_childless_tag = FeatureFlags.react_specific_warnings and children_count > 0 and tag.data == .e_string and tag.data.e_string.isUTF8() and js_lexer.ChildlessJSXTags.has(tag.data.e_string.slice(p.allocator));
children_count = if (is_childless_tag) 0 else children_count;
if (children_count != e_.children.len) {
// Error: meta is a void element tag and must neither have `children` nor use `dangerouslySetInnerHTML`.
// ^ from react-dom
- p.log.addWarningFmt(p.source, tag.loc, p.allocator, "<{s} /> is a void element and must not have \"children\"", .{tag.data.e_string.utf8}) catch {};
+ p.log.addWarningFmt(p.source, tag.loc, p.allocator, "<{s} /> is a void element and must not have \"children\"", .{tag.data.e_string.slice(p.allocator)}) catch {};
}
// TODO: maybe we should split these into two different AST Nodes
@@ -12395,7 +12419,7 @@ fn NewParser_(
const jsx_element = e_.right.data.e_jsx_element;
if (jsx_element.tag) |tag| {
if (tag.data == .e_string) {
- const tag_string = tag.data.e_string.utf8;
+ const tag_string = tag.data.e_string.slice(p.allocator);
if (js_ast.Macro.JSNode.Tag.names.get(tag_string)) |node_tag| {
call_args[1] = Expr{ .loc = tag.loc, .data = js_ast.Macro.JSNode.Tag.ids.get(node_tag) };
} else {
@@ -12420,7 +12444,7 @@ fn NewParser_(
const jsx_element = e_.left.data.e_jsx_element;
if (jsx_element.tag) |tag| {
if (tag.data == .e_string) {
- const tag_string = tag.data.e_string.utf8;
+ const tag_string = tag.data.e_string.slice(p.allocator);
if (js_ast.Macro.JSNode.Tag.names.get(tag_string)) |node_tag| {
call_args[0] = Expr{ .loc = tag.loc, .data = js_ast.Macro.JSNode.Tag.ids.get(node_tag) };
} else {
@@ -12632,7 +12656,9 @@ fn NewParser_(
}
}
- // TODO: fold string addition
+ if (foldStringAddition(e_.left, e_.right)) |res| {
+ return res;
+ }
},
.bin_sub => {
if (p.should_fold_numeric_constants) {
@@ -12822,11 +12848,9 @@ fn NewParser_(
}
if (e_.optional_chain == null and e_.index.data == .e_string and e_.index.data.e_string.isUTF8()) {
- const literal = e_.index.data.e_string.utf8;
+ const literal = e_.index.data.e_string.slice(p.allocator);
if (p.maybeRewritePropertyAccess(
expr.loc,
- in.assign_target,
- is_delete_target,
e_.target,
literal,
e_.index.loc,
@@ -12857,8 +12881,14 @@ fn NewParser_(
}
}
}
+ // "foo"[2]
+ } else if (e_.optional_chain == null and target.data == .e_string and e_.index.data == .e_number and target.data.e_string.isUTF8() and e_.index.data.e_number.value >= 0) {
+ const literal = target.data.e_string.slice(p.allocator);
+ const index = e_.index.data.e_number.toUsize();
+ if (literal.len > index) {
+ return p.e(E.String{ .data = literal[index .. index + 1] }, expr.loc);
+ }
}
-
// Create an error for assigning to an import namespace when bundling. Even
// though this is a run-time error, we make it a compile-time error when
// bundling because scope hoisting means these will no longer be run-time
@@ -12894,7 +12924,7 @@ fn NewParser_(
}
if (SideEffects.typeof(e_.value.data)) |typeof| {
- return p.e(E.String{ .utf8 = typeof }, expr.loc);
+ return p.e(E.String{ .data = typeof }, expr.loc);
}
},
.un_delete => {
@@ -13023,8 +13053,6 @@ fn NewParser_(
if (e_.optional_chain == null) {
if (p.maybeRewritePropertyAccess(
expr.loc,
- in.assign_target,
- is_delete_target,
e_.target,
e_.name,
e_.name_loc,
@@ -13034,11 +13062,9 @@ fn NewParser_(
}
if (comptime allow_macros) {
- if (p.macro_call_count > 0) {
- if (e_.target.data == .e_object and e_.target.data.e_object.was_originally_macro) {
- if (e_.target.get(e_.name)) |obj| {
- return obj;
- }
+ if (p.macro_call_count > 0 and e_.target.data == .e_object and e_.target.data.e_object.was_originally_macro) {
+ if (e_.target.get(e_.name)) |obj| {
+ return obj;
}
}
}
@@ -13166,7 +13192,7 @@ fn NewParser_(
key.data.isStringValue() and
strings.eqlComptime(
// __proto__ is utf8, assume it lives in refs
- key.data.e_string.utf8,
+ key.data.e_string.slice(p.allocator),
"__proto__",
)) {
if (has_proto) {
@@ -13869,8 +13895,6 @@ fn NewParser_(
fn maybeRewritePropertyAccess(
p: *P,
loc: logger.Loc,
- _: js_ast.AssignTarget,
- _: bool,
target: js_ast.Expr,
name: string,
name_loc: logger.Loc,
@@ -13896,6 +13920,12 @@ fn NewParser_(
}
}
},
+ .e_string => |str| {
+ // minify "long-string".length to 11
+ if (strings.eqlComptime(name, "length")) {
+ return p.e(E.Number{ .value = @intToFloat(f64, str.len()) }, loc);
+ }
+ },
else => {},
}
@@ -15513,7 +15543,7 @@ fn NewParser_(
}
const last = parts.len - 1;
- const is_tail_match = strings.eql(parts[last], index.index.data.e_string.utf8);
+ const is_tail_match = strings.eql(parts[last], index.index.data.e_string.slice(p.allocator));
return is_tail_match and p.isDotDefineMatch(index.target, parts[0..last]);
}
},
@@ -15906,7 +15936,7 @@ fn NewParser_(
p.expr_list.appendAssumeCapacity(p.e(E.Identifier{
.ref = ref,
}, loc));
- p.expr_list.appendAssumeCapacity(p.e(E.String{ .utf8 = name }, loc));
+ p.expr_list.appendAssumeCapacity(p.e(E.String{ .data = name }, loc));
return p.s(S.SExpr{
// I believe that this is a spot we can do $RefreshReg$(name)
.value = p.callRuntime(loc, "__name", p.expr_list.items[start..p.expr_list.items.len]),
@@ -16431,7 +16461,7 @@ fn NewParser_(
sourcefile_name = sourcefile_name[end..];
}
}
- commonjs_wrapper.data.e_call.args.ptr[1] = p.e(E.String{ .utf8 = sourcefile_name }, logger.Loc.Empty);
+ commonjs_wrapper.data.e_call.args.ptr[1] = p.e(E.String{ .data = sourcefile_name }, logger.Loc.Empty);
new_stmts_list[imports_list.len] = p.s(
S.ExportDefault{
@@ -16558,7 +16588,7 @@ fn NewParser_(
new_call_args[0] = p.e(E.Number{ .value = @intToFloat(f64, p.options.filepath_hash_for_hmr) }, logger.Loc.Empty);
// This helps us provide better error messages
- new_call_args[1] = p.e(E.String{ .utf8 = p.source.path.pretty }, logger.Loc.Empty);
+ new_call_args[1] = p.e(E.String{ .data = p.source.path.pretty }, logger.Loc.Empty);
if (p.options.features.react_fast_refresh) {
new_call_args[2] = p.e(E.Identifier{ .ref = p.jsx_refresh_runtime.ref }, logger.Loc.Empty);
}
@@ -16685,7 +16715,7 @@ fn NewParser_(
);
export_properties[named_export_i] = G.Property{
- .key = p.e(E.String{ .utf8 = named_export.key_ptr.* }, logger.Loc.Empty),
+ .key = p.e(E.String{ .data = named_export.key_ptr.* }, logger.Loc.Empty),
.value = p.e(
E.Arrow{
.args = &[_]G.Arg{},
diff --git a/src/js_printer.zig b/src/js_printer.zig
index 89bb82a1e..8bdaae5fc 100644
--- a/src/js_printer.zig
+++ b/src/js_printer.zig
@@ -926,9 +926,9 @@ pub fn NewPrinter(
pub fn bestQuoteCharForEString(p: *Printer, str: *const E.String, allow_backtick: bool) u8 {
if (str.isUTF8()) {
- return p.bestQuoteCharForString(str.utf8, allow_backtick);
+ return p.bestQuoteCharForString(str.data, allow_backtick);
} else {
- return p.bestQuoteCharForString(str.value, allow_backtick);
+ return p.bestQuoteCharForString(str.slice16(), allow_backtick);
}
}
@@ -1928,6 +1928,7 @@ pub fn NewPrinter(
p.print(if (e.value) "true" else "false");
},
.e_string => |e| {
+ e.resovleRopeIfNeeded(p.options.allocator);
// If this was originally a template literal, print it as one as long as we're not minifying
if (e.prefer_template) {
@@ -1956,14 +1957,17 @@ pub fn NewPrinter(
p.print("`");
if (e.head.isPresent()) {
+ e.head.resovleRopeIfNeeded(p.options.allocator);
+
p.printStringContent(&e.head, '`');
}
- for (e.parts) |part| {
+ for (e.parts) |*part| {
p.print("${");
p.printExpr(part.value, .lowest, ExprFlag.None());
p.print("}");
if (part.tail.isPresent()) {
+ part.tail.resovleRopeIfNeeded(p.options.allocator);
p.printStringContent(&part.tail, '`');
}
}
@@ -2294,9 +2298,9 @@ pub fn NewPrinter(
pub fn printStringContent(p: *Printer, str: *const E.String, c: u8) void {
if (!str.isUTF8()) {
// its already quoted for us!
- p.printQuotedUTF16(str.value, c);
+ p.printQuotedUTF16(str.slice16(), c);
} else {
- p.printUTF8StringEscapedQuotes(str.utf8, c);
+ p.printUTF8StringEscapedQuotes(str.data, c);
}
}
@@ -2479,6 +2483,7 @@ pub fn NewPrinter(
.e_string => |key| {
p.addSourceMapping(_key.loc);
if (key.isUTF8()) {
+ key.resovleRopeIfNeeded(p.options.allocator);
p.printSpaceBeforeIdentifier();
var allow_shorthand: bool = true;
// In react/cjs/react.development.js, there's part of a function like this:
@@ -2489,16 +2494,16 @@ pub fn NewPrinter(
// While each of those property keys are ASCII, a subset of ASCII is valid as the start of an identifier
// "=" and ":" are not valid
// So we need to check
- if ((comptime !is_json) and p.canPrintIdentifier(key.utf8)) {
- p.print(key.utf8);
+ if ((comptime !is_json) and p.canPrintIdentifier(key.data)) {
+ p.print(key.data);
} else {
allow_shorthand = false;
- const quote = p.bestQuoteCharForString(key.utf8, true);
+ const quote = p.bestQuoteCharForString(key.data, true);
if (quote == '`') {
p.print('[');
}
p.print(quote);
- p.printUTF8StringEscapedQuotes(key.utf8, quote);
+ p.printUTF8StringEscapedQuotes(key.data, quote);
p.print(quote);
if (quote == '`') {
p.print(']');
@@ -2521,7 +2526,7 @@ pub fn NewPrinter(
.e_import_identifier => |e| {
const ref = p.symbols.follow(e.ref);
if (p.symbols.get(ref)) |symbol| {
- if (symbol.namespace_alias == null and strings.eql(key.utf8, p.renamer.nameForSymbol(e.ref))) {
+ if (symbol.namespace_alias == null and strings.eql(key.data, p.renamer.nameForSymbol(e.ref))) {
if (item.initializer) |initial| {
p.printInitializer(initial);
}
@@ -2534,9 +2539,9 @@ pub fn NewPrinter(
else => {},
}
}
- } else if (p.canPrintIdentifierUTF16(key.value)) {
+ } else if (p.canPrintIdentifierUTF16(key.slice16())) {
p.printSpaceBeforeIdentifier();
- p.printIdentifierUTF16(key.value) catch unreachable;
+ p.printIdentifierUTF16(key.slice16()) catch unreachable;
// Use a shorthand property if the names are the same
if (item.value) |val| {
@@ -2547,7 +2552,7 @@ pub fn NewPrinter(
// esbuild doesn't have to do that...
// maybe it's a symptom of some other underlying issue
// or maybe, it's because i'm not lowering the same way that esbuild does.
- if (item.flags.contains(.was_shorthand) or strings.utf16EqlString(key.value, p.renamer.nameForSymbol(e.ref))) {
+ if (item.flags.contains(.was_shorthand) or strings.utf16EqlString(key.slice16(), p.renamer.nameForSymbol(e.ref))) {
if (item.initializer) |initial| {
p.printInitializer(initial);
}
@@ -2558,7 +2563,7 @@ pub fn NewPrinter(
.e_import_identifier => |e| {
const ref = p.symbols.follow(e.ref);
if (p.symbols.get(ref)) |symbol| {
- if (symbol.namespace_alias == null and strings.utf16EqlString(key.value, p.renamer.nameForSymbol(e.ref))) {
+ if (symbol.namespace_alias == null and strings.utf16EqlString(key.slice16(), p.renamer.nameForSymbol(e.ref))) {
if (item.initializer) |initial| {
p.printInitializer(initial);
}
@@ -2570,9 +2575,9 @@ pub fn NewPrinter(
}
}
} else {
- const c = p.bestQuoteCharForString(key.value, false);
+ const c = p.bestQuoteCharForString(key.slice16(), false);
p.print(c);
- p.printQuotedUTF16(key.value, c);
+ p.printQuotedUTF16(key.slice16(), c);
p.print(c);
}
},
@@ -2704,6 +2709,7 @@ pub fn NewPrinter(
switch (property.key.data) {
.e_string => |str| {
+ str.resovleRopeIfNeeded(p.options.allocator);
p.addSourceMapping(property.key.loc);
if (str.isUTF8()) {
@@ -2714,8 +2720,8 @@ pub fn NewPrinter(
// ^
// That needs to be:
// "aria-label": ariaLabel,
- if (p.canPrintIdentifier(str.utf8)) {
- p.printIdentifier(str.utf8);
+ if (p.canPrintIdentifier(str.data)) {
+ p.printIdentifier(str.data);
// Use a shorthand property if the names are the same
switch (property.value.data) {
@@ -2728,16 +2734,16 @@ pub fn NewPrinter(
else => {},
}
} else {
- p.printQuotedUTF8(str.utf8, false);
+ p.printQuotedUTF8(str.data, false);
}
- } else if (p.canPrintIdentifierUTF16(str.value)) {
+ } else if (p.canPrintIdentifierUTF16(str.slice16())) {
p.printSpaceBeforeIdentifier();
- p.printIdentifierUTF16(str.value) catch unreachable;
+ p.printIdentifierUTF16(str.slice16()) catch unreachable;
// Use a shorthand property if the names are the same
switch (property.value.data) {
.b_identifier => |id| {
- if (strings.utf16EqlString(str.value, p.renamer.nameForSymbol(id.ref))) {
+ if (strings.utf16EqlString(str.slice16(), p.renamer.nameForSymbol(id.ref))) {
p.maybePrintDefaultBindingValue(property);
continue;
}
@@ -2789,13 +2795,7 @@ pub fn NewPrinter(
pub fn printStmt(p: *Printer, stmt: Stmt) !void {
const prev_stmt_tag = p.prev_stmt_tag;
- // Give an extra newline for readaiblity
defer {
- //
- if (std.meta.activeTag(stmt.data) != .s_import and prev_stmt_tag == .s_import) {
- p.printNewline();
- }
-
p.prev_stmt_tag = std.meta.activeTag(stmt.data);
}
@@ -2879,6 +2879,8 @@ pub fn NewPrinter(
}
},
.s_empty => {
+ if (p.prev_stmt_tag == .s_empty and p.options.indent == 0) return;
+
p.printIndent();
p.print(";");
p.printNewline();
diff --git a/src/json_parser.zig b/src/json_parser.zig
index e6292488f..4bc442a5e 100644
--- a/src/json_parser.zig
+++ b/src/json_parser.zig
@@ -167,10 +167,7 @@ fn JSONLikeParser_(
.t_string_literal => {
var str: E.String = p.lexer.toEString();
if (comptime force_utf8) {
- if (str.value.len > 0) {
- str.utf8 = p.lexer.utf16ToString(str.value);
- str.value = &[_]u16{};
- }
+ str.toUTF8(p.allocator) catch unreachable;
}
try p.lexer.next();
@@ -469,21 +466,21 @@ pub const PackageJSONVersionChecker = struct {
// if you have multiple "name" fields in the package.json....
// first one wins
if (key.data == .e_string and value.data == .e_string) {
- if (!p.has_found_name and strings.eqlComptime(key.data.e_string.utf8, "name")) {
+ if (!p.has_found_name and strings.eqlComptime(key.data.e_string.data, "name")) {
const len = @minimum(
- value.data.e_string.utf8.len,
+ value.data.e_string.data.len,
p.found_name_buf.len,
);
- std.mem.copy(u8, &p.found_name_buf, value.data.e_string.utf8[0..len]);
+ std.mem.copy(u8, &p.found_name_buf, value.data.e_string.data[0..len]);
p.found_name = p.found_name_buf[0..len];
p.has_found_name = true;
- } else if (!p.has_found_version and strings.eqlComptime(key.data.e_string.utf8, "version")) {
+ } else if (!p.has_found_version and strings.eqlComptime(key.data.e_string.data, "version")) {
const len = @minimum(
- value.data.e_string.utf8.len,
+ value.data.e_string.data.len,
p.found_version_buf.len,
);
- std.mem.copy(u8, &p.found_version_buf, value.data.e_string.utf8[0..len]);
+ std.mem.copy(u8, &p.found_version_buf, value.data.e_string.data[0..len]);
p.found_version = p.found_version_buf[0..len];
p.has_found_version = true;
}
@@ -570,7 +567,7 @@ pub fn toAST(
},
.Slice => {
if (ptr_info.child == u8) {
- return Expr.init(js_ast.E.String, js_ast.E.String{ .utf8 = value }, logger.Loc.Empty);
+ return Expr.init(js_ast.E.String, js_ast.E.String.init(value), logger.Loc.Empty);
}
var exprs = try allocator.alloc(Expr, value.len);
@@ -584,7 +581,7 @@ pub fn toAST(
},
.Array => |Array| {
if (Array.child == u8) {
- return Expr.init(js_ast.E.String, js_ast.E.String{ .utf8 = value }, logger.Loc.Empty);
+ return Expr.init(js_ast.E.String, js_ast.E.String.init(value), logger.Loc.Empty);
}
var exprs = try allocator.alloc(Expr, value.len);
@@ -600,7 +597,7 @@ pub fn toAST(
var property_i: usize = 0;
inline for (fields) |field| {
properties[property_i] = G.Property{
- .key = Expr.init(E.String, E.String{ .utf8 = field.name }, logger.Loc.Empty),
+ .key = Expr.init(E.String, E.String{ .data = field.name }, logger.Loc.Empty),
.value = try toAST(allocator, field.field_type, @field(value, field.name)),
};
property_i += 1;
@@ -697,7 +694,7 @@ const JSONParserForMacro = JSONLikeParser(
var empty_object = E.Object{};
var empty_array = E.Array{};
-var empty_string = E.String{ .utf8 = "" };
+var empty_string = E.String{};
var empty_string_data = Expr.Data{ .e_string = &empty_string };
var empty_object_data = Expr.Data{ .e_object = &empty_object };
var empty_array_data = Expr.Data{ .e_array = &empty_array };
diff --git a/src/resolver/package_json.zig b/src/resolver/package_json.zig
index dc02ad358..280b27258 100644
--- a/src/resolver/package_json.zig
+++ b/src/resolver/package_json.zig
@@ -356,7 +356,7 @@ pub const PackageJSON = struct {
var count: usize = 0;
const items = array.items.slice();
for (items) |item| {
- count += @boolToInt(item.data == .e_string and item.data.e_string.utf8.len > 0);
+ count += @boolToInt(item.data == .e_string and item.data.e_string.data.len > 0);
}
switch (count) {
0 => {},
@@ -374,7 +374,7 @@ pub const PackageJSON = struct {
var list_i: usize = 0;
for (items) |item| {
- if (item.data == .e_string and item.data.e_string.utf8.len > 0) {
+ if (item.data == .e_string and item.data.e_string.data.len > 0) {
list[list_i] = item.data.e_string.string(allocator) catch unreachable;
list_i += 1;
}
@@ -398,7 +398,7 @@ pub const PackageJSON = struct {
while (array.next()) |expr| {
if (expr.data != .e_string) continue;
const e_str: *const js_ast.E.String = expr.data.e_string;
- if (e_str.utf8.len == 0 or e_str.utf8[0] != '.') continue;
+ if (e_str.data.len == 0 or e_str.data[0] != '.') continue;
valid_count += 1;
}
@@ -411,8 +411,8 @@ pub const PackageJSON = struct {
while (array.next()) |expr| {
if (expr.data != .e_string) continue;
const e_str: *const js_ast.E.String = expr.data.e_string;
- if (e_str.utf8.len == 0 or e_str.utf8[0] != '.') continue;
- extensions[i] = e_str.utf8;
+ if (e_str.data.len == 0 or e_str.data[0] != '.') continue;
+ extensions[i] = e_str.data;
i += 1;
}
}
@@ -512,7 +512,7 @@ pub const PackageJSON = struct {
for (remap_properties) |remap| {
const import_name = remap.key.?.asString(allocator) orelse continue;
const remap_value = remap.value.?;
- if (remap_value.data != .e_string or remap_value.data.e_string.utf8.len == 0) {
+ if (remap_value.data != .e_string or remap_value.data.e_string.data.len == 0) {
log.addWarningFmt(
json_source,
remap_value.loc,
@@ -523,7 +523,7 @@ pub const PackageJSON = struct {
continue;
}
- const remap_value_str = remap_value.data.e_string.utf8;
+ const remap_value_str = remap_value.data.e_string.data;
map.putAssumeCapacityNoClobber(import_name, remap_value_str);
}
diff --git a/src/runtime.zig b/src/runtime.zig
index 4b4a5a3e2..c79bf328f 100644
--- a/src/runtime.zig
+++ b/src/runtime.zig
@@ -275,6 +275,7 @@ pub const Runtime = struct {
allow_runtime: bool = true,
trim_unused_imports: bool = false,
+ should_fold_numeric_constants: bool = false,
replace_exports: ReplaceableExport.Map = .{},
diff --git a/src/string_immutable.zig b/src/string_immutable.zig
index 6114c7e06..a928f45a6 100644
--- a/src/string_immutable.zig
+++ b/src/string_immutable.zig
@@ -5,6 +5,7 @@ const string = @import("string_types.zig").string;
const stringZ = @import("string_types.zig").stringZ;
const CodePoint = @import("string_types.zig").CodePoint;
const bun = @import("global.zig");
+pub const joiner = @import("./string_joiner.zig");
const assert = std.debug.assert;
pub inline fn containsChar(self: string, char: u8) bool {
return indexOfChar(self, char) != null;
diff --git a/src/toml/toml_lexer.zig b/src/toml/toml_lexer.zig
index fac1016d6..d54b64863 100644
--- a/src/toml/toml_lexer.zig
+++ b/src/toml/toml_lexer.zig
@@ -1160,7 +1160,7 @@ pub const Lexer = struct {
}
pub inline fn toEString(lexer: *Lexer) js_ast.E.String {
- return js_ast.E.String{ .utf8 = lexer.string_literal_slice };
+ return js_ast.E.String{ .data = lexer.string_literal_slice };
}
pub fn raw(self: *Lexer) []const u8 {
diff --git a/src/toml/toml_parser.zig b/src/toml/toml_parser.zig
index 6673d5c41..cdfd49f5a 100644
--- a/src/toml/toml_parser.zig
+++ b/src/toml/toml_parser.zig
@@ -114,7 +114,7 @@ pub const TOML = struct {
return p.e(str, loc);
},
.t_identifier => {
- const str = E.String{ .utf8 = p.lexer.identifier };
+ const str = E.String{ .data = p.lexer.identifier };
try p.lexer.next();
return p.e(str, loc);
},
@@ -122,7 +122,7 @@ pub const TOML = struct {
try p.lexer.next();
return p.e(
E.String{
- .utf8 = "false",
+ .data = "false",
},
loc,
);
@@ -131,7 +131,7 @@ pub const TOML = struct {
try p.lexer.next();
return p.e(
E.String{
- .utf8 = "true",
+ .data = "true",
},
loc,
);
@@ -140,7 +140,7 @@ pub const TOML = struct {
.t_numeric_literal => {
const literal = p.lexer.raw();
try p.lexer.next();
- return p.e(E.String{ .utf8 = literal }, loc);
+ return p.e(E.String{ .data = literal }, loc);
},
else => return null,
@@ -298,7 +298,7 @@ pub const TOML = struct {
return p.e(str, loc);
},
.t_identifier => {
- var str: E.String = E.String{ .utf8 = p.lexer.identifier };
+ var str: E.String = E.String{ .data = p.lexer.identifier };
try p.lexer.next();
return p.e(str, loc);